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

@ -1,47 +0,0 @@
/**
******************************************************************************
* 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_

View File

@ -1,378 +0,0 @@
/**
******************************************************************************
* 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. *
******************************************************************************
*/
#include <alloy/backend/x64/lir/lir_builder.h>
#include <alloy/runtime/symbol_info.h>
using namespace alloy;
using namespace alloy::backend::x64;
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() {
return 0;
}
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->local) {
if (label->name) {
str->Append(".%s:\n", label->name);
} else {
str->Append(".label%d:\n", label->id);
}
} else {
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;
}
if (i->opcode == &LIR_OPCODE_COMMENT_info) {
str->Append(" ; %s\n", i->arg0<const char>());
i = i->next;
continue;
}
const LIROpcodeInfo* info = i->opcode;
str->Append(" ");
if (i->flags) {
str->Append("%s.%d", info->name, i->flags);
} else {
str->Append("%s", info->name);
}
if (i->arg0_type() != LIROperandType::NONE) {
str->Append(" ");
DumpArg(str, i->arg0_type(), (intptr_t)i + i->arg_offsets.arg0);
}
if (i->arg1_type() != LIROperandType::NONE) {
str->Append(", ");
DumpArg(str, i->arg1_type(), (intptr_t)i + i->arg_offsets.arg1);
}
if (i->arg2_type() != LIROperandType::NONE) {
str->Append(", ");
DumpArg(str, i->arg2_type(), (intptr_t)i + i->arg_offsets.arg2);
}
if (i->arg3_type() != LIROperandType::NONE) {
str->Append(", ");
DumpArg(str, i->arg3_type(), (intptr_t)i + i->arg_offsets.arg3);
}
str->Append("\n");
i = i->next;
}
block = block->next;
}
}
void LIRBuilder::DumpArg(StringBuffer* str, LIROperandType type,
intptr_t ptr) {
switch (type) {
case LIROperandType::NONE:
break;
case LIROperandType::FUNCTION:
if (true) {
auto target = (*(runtime::FunctionInfo**)ptr);
str->Append(target->name() ? target->name() : "<fn>");
}
break;
case LIROperandType::LABEL:
if (true) {
auto target = (*(LIRLabel**)ptr);
str->Append(target->name);
}
break;
case LIROperandType::OFFSET:
if (true) {
auto offset = (*(intptr_t*)ptr);
str->Append("+%lld", offset);
}
break;
case LIROperandType::STRING:
if (true) {
str->Append((*(char**)ptr));
}
break;
case LIROperandType::REGISTER:
if (true) {
LIRRegister* reg = (LIRRegister*)ptr;
if (reg->is_virtual()) {
switch (reg->type) {
case LIRRegisterType::REG8:
str->Append("v%d.i8", reg->id & 0x00FFFFFF);
break;
case LIRRegisterType::REG16:
str->Append("v%d.i16", reg->id & 0x00FFFFFF);
break;
case LIRRegisterType::REG32:
str->Append("v%d.i32", reg->id & 0x00FFFFFF);
break;
case LIRRegisterType::REG64:
str->Append("v%d.i64", reg->id & 0x00FFFFFF);
break;
case LIRRegisterType::REGXMM:
str->Append("v%d.xmm", reg->id & 0x00FFFFFF);
break;
}
} else {
str->Append(lir::register_names[(int)reg->name]);
}
}
break;
case LIROperandType::INT8_CONSTANT:
str->Append("%X", *(int8_t*)ptr);
break;
case LIROperandType::INT16_CONSTANT:
str->Append("%X", *(int16_t*)ptr);
break;
case LIROperandType::INT32_CONSTANT:
str->Append("%X", *(int32_t*)ptr);
break;
case LIROperandType::INT64_CONSTANT:
str->Append("%X", *(int64_t*)ptr);
break;
case LIROperandType::FLOAT32_CONSTANT:
str->Append("%F", *(float*)ptr);
break;
case LIROperandType::FLOAT64_CONSTANT:
str->Append("%F", *(double*)ptr);
break;
case LIROperandType::VEC128_CONSTANT:
if (true) {
vec128_t* value = (vec128_t*)ptr;
str->Append("(%F,%F,%F,%F)",
value->x, value->y, value->z, value->w);
}
break;
default: XEASSERTALWAYS(); break;
}
}
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(const char* name, bool local) {
LIRLabel* label = arena_->Alloc<LIRLabel>();
label->next = label->prev = NULL;
label->block = NULL;
label->id = next_label_id_++;
label->local = local;
label->tag = NULL;
if (!name) {
char label_name[32] = "l";
_itoa(label->id, label_name + 1, 10);
name = label_name;
}
size_t label_length = xestrlena(name);
label->name = (char*)arena_->Alloc(label_length + 1);
xe_copy_struct(label->name, name, label_length + 1);
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;
instr->arg_types = {
LIROperandType::NONE,
LIROperandType::NONE,
LIROperandType::NONE,
LIROperandType::NONE
};
return instr;
}
uint8_t LIRBuilder::AppendOperand(
LIRInstr* instr, LIROperandType& type, const char* value) {
type = LIROperandType::STRING;
size_t length = xestrlena(value);
auto ptr = (char*)arena_->Alloc(length + 1);
xe_copy_struct(ptr, value, length + 1);
return (uint8_t)((intptr_t)ptr - (intptr_t)instr);
}
uint8_t LIRBuilder::AppendOperand(
LIRInstr* instr, LIROperandType& type, hir::Value* value) {
if (value->IsConstant()) {
switch (value->type) {
case hir::INT8_TYPE:
return AppendOperand(instr, type, value->constant.i8);
case hir::INT16_TYPE:
return AppendOperand(instr, type, value->constant.i16);
case hir::INT32_TYPE:
return AppendOperand(instr, type, value->constant.i32);
case hir::INT64_TYPE:
return AppendOperand(instr, type, value->constant.i64);
case hir::FLOAT32_TYPE:
return AppendOperand(instr, type, value->constant.f32);
case hir::FLOAT64_TYPE:
return AppendOperand(instr, type, value->constant.f64);
case hir::VEC128_TYPE:
return AppendOperand(instr, type, value->constant.v128);
default:
XEASSERTALWAYS();
return 0;
}
} else {
LIRRegisterType reg_type;
switch (value->type) {
case hir::INT8_TYPE:
reg_type = LIRRegisterType::REG8;
break;
case hir::INT16_TYPE:
reg_type = LIRRegisterType::REG16;
break;
case hir::INT32_TYPE:
reg_type = LIRRegisterType::REG32;
break;
case hir::INT64_TYPE:
reg_type = LIRRegisterType::REG64;
break;
case hir::FLOAT32_TYPE:
reg_type = LIRRegisterType::REGXMM;
break;
case hir::FLOAT64_TYPE:
reg_type = LIRRegisterType::REGXMM;
break;
case hir::VEC128_TYPE:
reg_type = LIRRegisterType::REGXMM;
break;
default:
XEASSERTALWAYS();
return 0;
}
// Make it uniqueish by putting it +20000000
uint32_t reg_id = 0x20000000 + value->ordinal;
return AppendOperand(instr, type, LIRRegister(reg_type, reg_id));
}
}
void LIRBuilder::Comment(const char* format, ...) {
char buffer[1024];
va_list args;
va_start(args, format);
xevsnprintfa(buffer, 1024, format, args);
va_end(args);
auto instr = AppendInstr(LIR_OPCODE_COMMENT_info);
instr->arg_offsets.arg0 =
AppendOperand(instr, instr->arg_types.arg0, buffer);
}

View File

@ -1,189 +0,0 @@
/**
******************************************************************************
* 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_BUILDER_H_
#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>
#include <alloy/hir/value.h>
namespace alloy {
namespace backend {
namespace x64 {
class X64Backend;
namespace lir {
class LIRBuilder {
public:
LIRBuilder(X64Backend* backend);
~LIRBuilder();
void Reset();
int Finalize();
void Dump(StringBuffer* str);
Arena* arena() const { return arena_; }
LIRBlock* first_block() const { return block_head_; }
LIRBlock* current_block() const;
LIRInstr* last_instr() const;
LIRLabel* NewLabel(const char* name = 0, bool local = false);
LIRLabel* NewLocalLabel() { return NewLabel(0, true); }
void MarkLabel(LIRLabel* label, LIRBlock* block = 0);
// TODO(benvanik): allocations
LIRBlock* AppendBlock();
void EndBlock();
void Nop() { AppendInstr(LIR_OPCODE_NOP_info, 0); }
void Comment(const char* format, ...);
void SourceOffset(uintptr_t offset) { AppendInstr(LIR_OPCODE_SOURCE_OFFSET_info, 0, offset); }
void DebugBreak() { AppendInstr(LIR_OPCODE_DEBUG_BREAK_info, 0); }
void Trap() { AppendInstr(LIR_OPCODE_TRAP_info, 0); }
template<typename A0, typename A1>
void Mov(A0& a, A1& b) { AppendInstr(LIR_OPCODE_MOV_info, 0, a, b); }
template<typename A0, typename A1, typename A2>
void Mov(A0& a, A1& b, A2& c) { AppendInstr(LIR_OPCODE_MOV_info, 0, a, b, c); }
template<typename A0, typename A1>
void MovZX(A0& a, A1& b) { AppendInstr(LIR_OPCODE_MOV_ZX_info, 0, a, b); }
template<typename A0, typename A1>
void MovSX(A0& a, A1& b) { AppendInstr(LIR_OPCODE_MOV_ZX_info, 0, a, b); }
template<typename A0, typename A1>
void Test(A0& a, A1& b) { AppendInstr(LIR_OPCODE_TEST_info, 0, a, b); }
template<typename A0>
void Jump(A0& target) { AppendInstr(LIR_OPCODE_JUMP_info, 0, target); }
void JumpEQ(LIRLabel* target) { AppendInstr(LIR_OPCODE_JUMP_EQ_info, 0, target); }
void JumpNE(LIRLabel* target) { AppendInstr(LIR_OPCODE_JUMP_NE_info, 0, target); }
private:
void DumpArg(StringBuffer* str, LIROperandType type, intptr_t ptr);
LIRInstr* AppendInstr(const LIROpcodeInfo& opcode, uint16_t flags = 0);
XEFORCEINLINE LIROperandType GetOperandType(runtime::FunctionInfo*) { return LIROperandType::FUNCTION; }
XEFORCEINLINE LIROperandType GetOperandType(LIRLabel*) { return LIROperandType::LABEL; }
XEFORCEINLINE LIROperandType GetOperandType(uintptr_t) { return LIROperandType::OFFSET; }
XEFORCEINLINE LIROperandType GetOperandType(const char*) { return LIROperandType::STRING; }
XEFORCEINLINE LIROperandType GetOperandType(LIRRegister&) { return LIROperandType::REGISTER; }
XEFORCEINLINE LIROperandType GetOperandType(int8_t) { return LIROperandType::INT8_CONSTANT; }
XEFORCEINLINE LIROperandType GetOperandType(int16_t) { return LIROperandType::INT16_CONSTANT; }
XEFORCEINLINE LIROperandType GetOperandType(int32_t) { return LIROperandType::INT32_CONSTANT; }
XEFORCEINLINE LIROperandType GetOperandType(int64_t) { return LIROperandType::INT64_CONSTANT; }
XEFORCEINLINE LIROperandType GetOperandType(float) { return LIROperandType::FLOAT32_CONSTANT; }
XEFORCEINLINE LIROperandType GetOperandType(double) { return LIROperandType::FLOAT64_CONSTANT; }
XEFORCEINLINE LIROperandType GetOperandType(vec128_t&) { return LIROperandType::VEC128_CONSTANT; }
LIROperandType GetOperandType(hir::Value* value) {
if (value->IsConstant()) {
switch (value->type) {
case hir::INT8_TYPE:
return LIROperandType::INT8_CONSTANT;
case hir::INT16_TYPE:
return LIROperandType::INT16_CONSTANT;
case hir::INT32_TYPE:
return LIROperandType::INT32_CONSTANT;
case hir::INT64_TYPE:
return LIROperandType::INT64_CONSTANT;
case hir::FLOAT32_TYPE:
return LIROperandType::FLOAT32_CONSTANT;
case hir::FLOAT64_TYPE:
return LIROperandType::FLOAT64_CONSTANT;
case hir::VEC128_TYPE:
return LIROperandType::VEC128_CONSTANT;
default:
XEASSERTALWAYS();
return LIROperandType::INT8_CONSTANT;
}
} else {
return LIROperandType::REGISTER;
}
}
template<typename T>
uint8_t AppendOperand(LIRInstr* instr, LIROperandType& type, T& value) {
type = GetOperandType(value);
auto ptr = arena_->Alloc<T>();
*ptr = value;
return (uint8_t)((intptr_t)ptr - (intptr_t)instr);
}
uint8_t AppendOperand(LIRInstr* instr, LIROperandType& type, const char* value);
uint8_t AppendOperand(LIRInstr* instr, LIROperandType& type, hir::Value* value);
template<typename A0>
LIRInstr* AppendInstr(const LIROpcodeInfo& opcode, uint16_t flags, A0& arg0) {
auto instr = AppendInstr(opcode, flags);
instr->arg_offsets.arg0 =
AppendOperand(instr, instr->arg_types.arg0, arg0);
return instr;
}
template<typename A0, typename A1>
LIRInstr* AppendInstr(const LIROpcodeInfo& opcode, uint16_t flags, A0& arg0, A1& arg1) {
auto instr = AppendInstr(opcode, flags);
instr->arg_offsets.arg0 =
AppendOperand(instr, instr->arg_types.arg0, arg0);
instr->arg_offsets.arg1 =
AppendOperand(instr, instr->arg_types.arg1, arg1);
return instr;
}
template<typename A0, typename A1, typename A2>
LIRInstr* AppendInstr(const LIROpcodeInfo& opcode, uint16_t flags, A0& arg0, A1& arg1, A2& arg2) {
auto instr = AppendInstr(opcode, flags);
instr->arg_offsets.arg0 =
AppendOperand(instr, instr->arg_types.arg0, arg0);
instr->arg_offsets.arg1 =
AppendOperand(instr, instr->arg_types.arg1, arg1);
instr->arg_offsets.arg2 =
AppendOperand(instr, instr->arg_types.arg2, arg2);
return instr;
}
template<typename A0, typename A1, typename A2, typename A3>
LIRInstr* AppendInstr(const LIROpcodeInfo& opcode, uint16_t flags, A0& arg0, A1& arg1, A2& arg2, A3& arg3) {
auto instr = AppendInstr(opcode, flags);
instr->arg_offsets.arg0 =
AppendOperand(instr, instr->arg_types.arg0, arg0);
instr->arg_offsets.arg1 =
AppendOperand(instr, instr->arg_types.arg1, arg1);
instr->arg_offsets.arg2 =
AppendOperand(instr, instr->arg_types.arg2, arg2);
instr->arg_offsets.arg3 =
AppendOperand(instr, instr->arg_types.arg3, arg3);
return instr;
}
private:
X64Backend* backend_;
Arena* arena_;
uint32_t next_label_id_;
LIRBlock* block_head_;
LIRBlock* block_tail_;
LIRBlock* current_block_;
};
} // namespace lir
} // namespace x64
} // namespace backend
} // namespace alloy
#endif // ALLOY_BACKEND_X64_LIR_LIR_BUILDER_H_

View File

@ -1,76 +0,0 @@
/**
******************************************************************************
* 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. *
******************************************************************************
*/
#include <alloy/backend/x64/lir/lir_instr.h>
using namespace alloy;
using namespace alloy::backend::x64::lir;
namespace alloy {
namespace backend {
namespace x64 {
namespace lir {
const char* register_names[] = {
"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",
};
} // namespace lir
} // namespace x64
} // namespace backend
} // namespace alloy
void LIRInstr::Remove() {
if (next) {
next->prev = prev;
}
if (prev) {
prev->next = next;
}
if (block->instr_head == this) {
block->instr_head = next;
}
if (block->instr_tail == this) {
block->instr_tail = prev;
}
}

View File

@ -1,146 +0,0 @@
/**
******************************************************************************
* 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_INSTR_H_
#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 class LIRRegisterName : uint32_t {
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,
VREG0 = 0x10000000,
};
extern const char* register_names[74];
enum class LIRRegisterType : uint32_t {
REG8,
REG16,
REG32,
REG64,
REGXMM,
};
typedef struct LIRRegister_s {
LIRRegisterType type;
union {
uint32_t id;
LIRRegisterName name;
};
struct LIRRegister_s(LIRRegisterType _type, uint32_t _id) :
type(_type), id((uint32_t)LIRRegisterName::VREG0 + _id) {}
struct LIRRegister_s(LIRRegisterType _type, LIRRegisterName _name) :
type(_type), name(_name) {}
bool is_virtual() const { return id > (uint32_t)LIRRegisterName::VREG0; }
} LIRRegister;
enum class LIROperandType : uint8_t {
NONE = 0,
FUNCTION,
LABEL,
OFFSET,
STRING,
REGISTER,
INT8_CONSTANT,
INT16_CONSTANT,
INT32_CONSTANT,
INT64_CONSTANT,
FLOAT32_CONSTANT,
FLOAT64_CONSTANT,
VEC128_CONSTANT,
};
class LIRInstr {
public:
LIRBlock* block;
LIRInstr* next;
LIRInstr* prev;
const LIROpcodeInfo* opcode;
uint16_t flags;
struct {
LIROperandType arg0;
LIROperandType arg1;
LIROperandType arg2;
LIROperandType arg3;
} arg_types;
struct {
uint8_t arg0;
uint8_t arg1;
uint8_t arg2;
uint8_t arg3;
} arg_offsets;
LIROperandType arg0_type() const { return arg_types.arg0; }
LIROperandType arg1_type() const { return arg_types.arg1; }
LIROperandType arg2_type() const { return arg_types.arg2; }
LIROperandType arg3_type() const { return arg_types.arg3; }
template<typename T> T* arg0() { return (T*)(((uint8_t*)this) + arg_offsets.arg0); }
template<typename T> T* arg1() { return (T*)(((uint8_t*)this) + arg_offsets.arg1); }
template<typename T> T* arg2() { return (T*)(((uint8_t*)this) + arg_offsets.arg2); }
template<typename T> T* arg3() { return (T*)(((uint8_t*)this) + arg_offsets.arg3); }
void Remove();
};
} // namespace lir
} // namespace x64
} // namespace backend
} // namespace alloy
#endif // ALLOY_BACKEND_X64_LIR_LIR_INSTR_H_

View File

@ -1,44 +0,0 @@
/**
******************************************************************************
* 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;
bool local;
void* tag;
};
} // namespace lir
} // namespace x64
} // namespace backend
} // namespace alloy
#endif // ALLOY_BACKEND_X64_LIR_LIR_LABEL_H_

View File

@ -1,39 +0,0 @@
/**
******************************************************************************
* 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. *
******************************************************************************
*/
#include <alloy/backend/x64/lir/lir_opcodes.h>
using namespace alloy;
using namespace alloy::backend::x64::lir;
namespace alloy {
namespace backend {
namespace x64 {
namespace lir {
#define DEFINE_OPCODE(num, string_name, flags) \
static const LIROpcodeInfo num##_info = { flags, string_name, num, };
#include <alloy/backend/x64/lir/lir_opcodes.inl>
#undef DEFINE_OPCODE
const LIROpcodeInfo& GetOpcodeInfo(LIROpcode opcode) {
static const LIROpcodeInfo* lookup[__LIR_OPCODE_MAX_VALUE] = {
#define DEFINE_OPCODE(num, string_name, flags) \
&num##_info,
#include <alloy/backend/x64/lir/lir_opcodes.inl>
#undef DEFINE_OPCODE
};
return *lookup[opcode];
}
} // namespace lir
} // namespace x64
} // namespace backend
} // namespace alloy

View File

@ -1,73 +0,0 @@
/**
******************************************************************************
* 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_OPCODES_H_
#define ALLOY_BACKEND_X64_LIR_LIR_OPCODES_H_
#include <alloy/core.h>
namespace alloy {
namespace backend {
namespace x64 {
namespace lir {
enum LIROpcode {
LIR_OPCODE_NOP,
LIR_OPCODE_COMMENT,
LIR_OPCODE_SOURCE_OFFSET,
LIR_OPCODE_DEBUG_BREAK,
LIR_OPCODE_TRAP,
LIR_OPCODE_MOV,
LIR_OPCODE_MOV_ZX,
LIR_OPCODE_MOV_SX,
LIR_OPCODE_TEST,
LIR_OPCODE_JUMP,
LIR_OPCODE_JUMP_EQ,
LIR_OPCODE_JUMP_NE,
__LIR_OPCODE_MAX_VALUE, // Keep at end.
};
enum LIROpcodeFlags {
LIR_OPCODE_FLAG_BRANCH = (1 << 1),
LIR_OPCODE_FLAG_MEMORY = (1 << 2),
LIR_OPCODE_FLAG_COMMUNATIVE = (1 << 3),
LIR_OPCODE_FLAG_VOLATILE = (1 << 4),
LIR_OPCODE_FLAG_IGNORE = (1 << 5),
LIR_OPCODE_FLAG_HIDE = (1 << 6),
};
typedef struct {
uint32_t flags;
const char* name;
LIROpcode num;
} LIROpcodeInfo;
#define DEFINE_OPCODE(num, string_name, flags) \
extern const LIROpcodeInfo num##_info;
#include <alloy/backend/x64/lir/lir_opcodes.inl>
#undef DEFINE_OPCODE
extern const LIROpcodeInfo& GetOpcodeInfo(LIROpcode opcode);
} // namespace lir
} // namespace x64
} // namespace backend
} // namespace alloy
#endif // ALLOY_BACKEND_X64_LIR_LIR_OPCODES_H_

View File

@ -1,61 +0,0 @@
/**
******************************************************************************
* 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. *
******************************************************************************
*/
DEFINE_OPCODE(
LIR_OPCODE_NOP,
"nop",
LIR_OPCODE_FLAG_IGNORE)
DEFINE_OPCODE(
LIR_OPCODE_COMMENT,
"comment",
LIR_OPCODE_FLAG_IGNORE)
DEFINE_OPCODE(
LIR_OPCODE_SOURCE_OFFSET,
"source_offset",
LIR_OPCODE_FLAG_IGNORE | LIR_OPCODE_FLAG_HIDE)
DEFINE_OPCODE(
LIR_OPCODE_DEBUG_BREAK,
"debug_break",
0)
DEFINE_OPCODE(
LIR_OPCODE_TRAP,
"trap",
0)
DEFINE_OPCODE(
LIR_OPCODE_MOV,
"mov",
0)
DEFINE_OPCODE(
LIR_OPCODE_MOV_ZX,
"mov_zx",
0)
DEFINE_OPCODE(
LIR_OPCODE_MOV_SX,
"mov_sx",
0)
DEFINE_OPCODE(
LIR_OPCODE_TEST,
"test",
0)
DEFINE_OPCODE(
LIR_OPCODE_JUMP,
"jump",
0)
DEFINE_OPCODE(
LIR_OPCODE_JUMP_EQ,
"jump_eq",
0)
DEFINE_OPCODE(
LIR_OPCODE_JUMP_NE,
"jump_ne",
0)

View File

@ -1,15 +0,0 @@
# Copyright 2013 Ben Vanik. All Rights Reserved.
{
'sources': [
'lir_block.h',
'lir_builder.cc',
'lir_builder.h',
'lir_instr.cc',
'lir_instr.h',
'lir_label.h',
'lir_opcodes.cc',
'lir_opcodes.h',
'lir_opcodes.inl',
'tracing.h',
],
}

View File

@ -1,39 +0,0 @@
/**
******************************************************************************
* 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_TRACING_H_
#define ALLOY_BACKEND_X64_LIR_TRACING_H_
#include <alloy/backend/x64/tracing.h>
namespace alloy {
namespace backend {
namespace x64 {
namespace lir {
const uint32_t ALLOY_BACKEND_X64_LIR =
alloy::backend::x64::EventType::ALLOY_BACKEND_X64_LIR;
class EventType {
public:
enum {
ALLOY_BACKEND_X64_LIR_FOO = ALLOY_BACKEND_X64_LIR | (1),
};
};
} // namespace lir
} // namespace x64
} // namespace backend
} // namespace alloy
#endif // ALLOY_BACKEND_X64_LIR_TRACING_H_

View File

@ -9,28 +9,42 @@
#include <alloy/backend/x64/lowering/lowering_sequences.h>
#include <alloy/backend/x64/x64_emitter.h>
#include <alloy/backend/x64/lowering/lowering_table.h>
using namespace alloy;
using namespace alloy::backend::x64;
using namespace alloy::backend::x64::lir;
using namespace alloy::backend::x64::lowering;
using namespace alloy::hir;
using namespace Xbyak;
namespace {
#define UNIMPLEMENTED_SEQ()
// TODO(benvanik): emit traces/printfs/etc
} // namespace
void alloy::backend::x64::lowering::RegisterSequences(LoweringTable* table) {
// --------------------------------------------------------------------------
// General
// --------------------------------------------------------------------------
table->AddSequence(OPCODE_COMMENT, [](LIRBuilder& lb, Instr*& instr) {
char* str = (char*)instr->src1.offset;
lb.Comment(str);
table->AddSequence(OPCODE_COMMENT, [](X64Emitter& e, Instr*& instr) {
//char* str = (char*)instr->src1.offset;
//lb.Comment(str);
UNIMPLEMENTED_SEQ();
instr = instr->next;
return true;
});
table->AddSequence(OPCODE_NOP, [](LIRBuilder& lb, Instr*& instr) {
lb.Nop();
table->AddSequence(OPCODE_NOP, [](X64Emitter& e, Instr*& instr) {
// If we got this, chances are we want it.
e.nop();
instr = instr->next;
return true;
});
@ -39,42 +53,53 @@ void alloy::backend::x64::lowering::RegisterSequences(LoweringTable* table) {
// Debugging
// --------------------------------------------------------------------------
table->AddSequence(OPCODE_SOURCE_OFFSET, [](LIRBuilder& lb, Instr*& instr) {
table->AddSequence(OPCODE_SOURCE_OFFSET, [](X64Emitter& e, Instr*& instr) {
// TODO(benvanik): translate source offsets for mapping? We're just passing
// down the original offset - it may be nice to have two.
lb.SourceOffset(instr->src1.offset);
//lb.SourceOffset(instr->src1.offset);
UNIMPLEMENTED_SEQ();
instr = instr->next;
return true;
});
table->AddSequence(OPCODE_DEBUG_BREAK, [](LIRBuilder& lb, Instr*& instr) {
lb.DebugBreak();
table->AddSequence(OPCODE_DEBUG_BREAK, [](X64Emitter& e, Instr*& instr) {
// TODO(benvanik): insert a call to the debug break function to let the
// debugger know.
e.db(0xCC);
instr = instr->next;
return true;
});
table->AddSequence(OPCODE_DEBUG_BREAK_TRUE, [](LIRBuilder& lb, Instr*& instr) {
auto skip_label = lb.NewLocalLabel();
lb.Test(instr->src1.value, instr->src1.value);
lb.JumpNE(skip_label);
lb.DebugBreak();
lb.MarkLabel(skip_label);
table->AddSequence(OPCODE_DEBUG_BREAK_TRUE, [](X64Emitter& e, Instr*& instr) {
e.inLocalLabel();
//e.test(e.rax, e.rax);
e.jne(".x");
// TODO(benvanik): insert a call to the debug break function to let the
// debugger know.
e.db(0xCC);
e.L(".x");
e.outLocalLabel();
instr = instr->next;
return true;
});
table->AddSequence(OPCODE_TRAP, [](LIRBuilder& lb, Instr*& instr) {
lb.Trap();
table->AddSequence(OPCODE_TRAP, [](X64Emitter& e, Instr*& instr) {
// TODO(benvanik): insert a call to the trap function to let the
// debugger know.
e.db(0xCC);
instr = instr->next;
return true;
});
table->AddSequence(OPCODE_TRAP_TRUE, [](LIRBuilder& lb, Instr*& instr) {
auto skip_label = lb.NewLocalLabel();
lb.Test(instr->src1.value, instr->src1.value);
lb.JumpNE(skip_label);
lb.Trap();
lb.MarkLabel(skip_label);
table->AddSequence(OPCODE_TRAP_TRUE, [](X64Emitter& e, Instr*& instr) {
e.inLocalLabel();
//e.test(rax, rax);
e.jne(".x");
// TODO(benvanik): insert a call to the trap function to let the
// debugger know.
e.db(0xCC);
e.L(".x");
e.outLocalLabel();
instr = instr->next;
return true;
});
@ -83,46 +108,48 @@ void alloy::backend::x64::lowering::RegisterSequences(LoweringTable* table) {
// Calls
// --------------------------------------------------------------------------
table->AddSequence(OPCODE_CALL, [](LIRBuilder& lb, Instr*& instr) {
// TODO
table->AddSequence(OPCODE_CALL, [](X64Emitter& e, Instr*& instr) {
UNIMPLEMENTED_SEQ();
instr = instr->next;
return true;
});
table->AddSequence(OPCODE_CALL_TRUE, [](LIRBuilder& lb, Instr*& instr) {
auto skip_label = lb.NewLocalLabel();
lb.Test(instr->src1.value, instr->src1.value);
lb.JumpNE(skip_label);
// TODO
lb.MarkLabel(skip_label);
table->AddSequence(OPCODE_CALL_TRUE, [](X64Emitter& e, Instr*& instr) {
//auto skip_label = lb.NewLocalLabel();
//lb.Test(instr->src1.value, instr->src1.value);
//lb.JumpNE(skip_label);
//// TODO
//lb.MarkLabel(skip_label);
UNIMPLEMENTED_SEQ();
instr = instr->next;
return true;
});
table->AddSequence(OPCODE_CALL_INDIRECT, [](LIRBuilder& lb, Instr*& instr) {
// TODO
table->AddSequence(OPCODE_CALL_INDIRECT, [](X64Emitter& e, Instr*& instr) {
UNIMPLEMENTED_SEQ();
instr = instr->next;
return true;
});
table->AddSequence(OPCODE_CALL_INDIRECT_TRUE, [](LIRBuilder& lb, Instr*& instr) {
auto skip_label = lb.NewLocalLabel();
lb.Test(instr->src1.value, instr->src1.value);
lb.JumpNE(skip_label);
// TODO
lb.MarkLabel(skip_label);
table->AddSequence(OPCODE_CALL_INDIRECT_TRUE, [](X64Emitter& e, Instr*& instr) {
//auto skip_label = lb.NewLocalLabel();
//lb.Test(instr->src1.value, instr->src1.value);
//lb.JumpNE(skip_label);
//UNIMPLEMENTED_SEQ();
//lb.MarkLabel(skip_label);
UNIMPLEMENTED_SEQ();
instr = instr->next;
return true;
});
table->AddSequence(OPCODE_RETURN, [](LIRBuilder& lb, Instr*& instr) {
// TODO
table->AddSequence(OPCODE_RETURN, [](X64Emitter& e, Instr*& instr) {
UNIMPLEMENTED_SEQ();
instr = instr->next;
return true;
});
table->AddSequence(OPCODE_SET_RETURN_ADDRESS, [](LIRBuilder& lb, Instr*& instr) {
// TODO
table->AddSequence(OPCODE_SET_RETURN_ADDRESS, [](X64Emitter& e, Instr*& instr) {
UNIMPLEMENTED_SEQ();
instr = instr->next;
return true;
});
@ -131,25 +158,28 @@ void alloy::backend::x64::lowering::RegisterSequences(LoweringTable* table) {
// Branches
// --------------------------------------------------------------------------
table->AddSequence(OPCODE_BRANCH, [](LIRBuilder& lb, Instr*& instr) {
auto target = (LIRLabel*)instr->src1.label->tag;
lb.Jump(target);
table->AddSequence(OPCODE_BRANCH, [](X64Emitter& e, Instr*& instr) {
/*auto target = (LIRLabel*)instr->src1.label->tag;
lb.Jump(target);*/
UNIMPLEMENTED_SEQ();
instr = instr->next;
return true;
});
table->AddSequence(OPCODE_BRANCH_TRUE, [](LIRBuilder& lb, Instr*& instr) {
lb.Test(instr->src1.value, instr->src1.value);
table->AddSequence(OPCODE_BRANCH_TRUE, [](X64Emitter& e, Instr*& instr) {
/*lb.Test(instr->src1.value, instr->src1.value);
auto target = (LIRLabel*)instr->src2.label->tag;
lb.JumpEQ(target);
lb.JumpEQ(target);*/
UNIMPLEMENTED_SEQ();
instr = instr->next;
return true;
});
table->AddSequence(OPCODE_BRANCH_FALSE, [](LIRBuilder& lb, Instr*& instr) {
lb.Test(instr->src1.value, instr->src1.value);
table->AddSequence(OPCODE_BRANCH_FALSE, [](X64Emitter& e, Instr*& instr) {
/*lb.Test(instr->src1.value, instr->src1.value);
auto target = (LIRLabel*)instr->src2.label->tag;
lb.JumpNE(target);
lb.JumpNE(target);*/
UNIMPLEMENTED_SEQ();
instr = instr->next;
return true;
});
@ -158,56 +188,61 @@ void alloy::backend::x64::lowering::RegisterSequences(LoweringTable* table) {
// Types
// --------------------------------------------------------------------------
table->AddSequence(OPCODE_ASSIGN, [](LIRBuilder& lb, Instr*& instr) {
lb.Mov(instr->dest, instr->src1.value);
table->AddSequence(OPCODE_ASSIGN, [](X64Emitter& e, Instr*& instr) {
//lb.Mov(instr->dest, instr->src1.value);
UNIMPLEMENTED_SEQ();
instr = instr->next;
return true;
});
table->AddSequence(OPCODE_CAST, [](LIRBuilder& lb, Instr*& instr) {
lb.Mov(instr->dest, instr->src1.value);
table->AddSequence(OPCODE_CAST, [](X64Emitter& e, Instr*& instr) {
//lb.Mov(instr->dest, instr->src1.value);
UNIMPLEMENTED_SEQ();
instr = instr->next;
return true;
});
table->AddSequence(OPCODE_ZERO_EXTEND, [](LIRBuilder& lb, Instr*& instr) {
lb.MovZX(instr->dest, instr->src1.value);
table->AddSequence(OPCODE_ZERO_EXTEND, [](X64Emitter& e, Instr*& instr) {
//lb.MovZX(instr->dest, instr->src1.value);
UNIMPLEMENTED_SEQ();
instr = instr->next;
return true;
});
table->AddSequence(OPCODE_SIGN_EXTEND, [](LIRBuilder& lb, Instr*& instr) {
lb.MovSX(instr->dest, instr->src1.value);
table->AddSequence(OPCODE_SIGN_EXTEND, [](X64Emitter& e, Instr*& instr) {
//lb.MovSX(instr->dest, instr->src1.value);
UNIMPLEMENTED_SEQ();
instr = instr->next;
return true;
});
table->AddSequence(OPCODE_TRUNCATE, [](LIRBuilder& lb, Instr*& instr) {
lb.Mov(instr->dest, instr->src1.value);
table->AddSequence(OPCODE_TRUNCATE, [](X64Emitter& e, Instr*& instr) {
//lb.Mov(instr->dest, instr->src1.value);
UNIMPLEMENTED_SEQ();
instr = instr->next;
return true;
});
table->AddSequence(OPCODE_CONVERT, [](LIRBuilder& lb, Instr*& instr) {
// TODO
table->AddSequence(OPCODE_CONVERT, [](X64Emitter& e, Instr*& instr) {
UNIMPLEMENTED_SEQ();
instr = instr->next;
return true;
});
table->AddSequence(OPCODE_ROUND, [](LIRBuilder& lb, Instr*& instr) {
// TODO
table->AddSequence(OPCODE_ROUND, [](X64Emitter& e, Instr*& instr) {
UNIMPLEMENTED_SEQ();
instr = instr->next;
return true;
});
table->AddSequence(OPCODE_VECTOR_CONVERT_I2F, [](LIRBuilder& lb, Instr*& instr) {
// TODO
table->AddSequence(OPCODE_VECTOR_CONVERT_I2F, [](X64Emitter& e, Instr*& instr) {
UNIMPLEMENTED_SEQ();
instr = instr->next;
return true;
});
table->AddSequence(OPCODE_VECTOR_CONVERT_F2I, [](LIRBuilder& lb, Instr*& instr) {
// TODO
table->AddSequence(OPCODE_VECTOR_CONVERT_F2I, [](X64Emitter& e, Instr*& instr) {
UNIMPLEMENTED_SEQ();
instr = instr->next;
return true;
});
@ -218,20 +253,20 @@ void alloy::backend::x64::lowering::RegisterSequences(LoweringTable* table) {
// specials for zeroing/etc (xor/etc)
table->AddSequence(OPCODE_LOAD_VECTOR_SHL, [](LIRBuilder& lb, Instr*& instr) {
// TODO
table->AddSequence(OPCODE_LOAD_VECTOR_SHL, [](X64Emitter& e, Instr*& instr) {
UNIMPLEMENTED_SEQ();
instr = instr->next;
return true;
});
table->AddSequence(OPCODE_LOAD_VECTOR_SHR, [](LIRBuilder& lb, Instr*& instr) {
// TODO
table->AddSequence(OPCODE_LOAD_VECTOR_SHR, [](X64Emitter& e, Instr*& instr) {
UNIMPLEMENTED_SEQ();
instr = instr->next;
return true;
});
table->AddSequence(OPCODE_LOAD_CLOCK, [](LIRBuilder& lb, Instr*& instr) {
// TODO
table->AddSequence(OPCODE_LOAD_CLOCK, [](X64Emitter& e, Instr*& instr) {
UNIMPLEMENTED_SEQ();
instr = instr->next;
return true;
});
@ -240,20 +275,22 @@ void alloy::backend::x64::lowering::RegisterSequences(LoweringTable* table) {
// Context
// --------------------------------------------------------------------------
table->AddSequence(OPCODE_LOAD_CONTEXT, [](LIRBuilder& lb, Instr*& instr) {
lb.Mov(
table->AddSequence(OPCODE_LOAD_CONTEXT, [](X64Emitter& e, Instr*& instr) {
/*lb.Mov(
instr->dest,
LIRRegister(LIRRegisterType::REG64, LIRRegisterName::RCX),
instr->src1.offset);
instr->src1.offset);*/
UNIMPLEMENTED_SEQ();
instr = instr->next;
return true;
});
table->AddSequence(OPCODE_STORE_CONTEXT, [](LIRBuilder& lb, Instr*& instr) {
lb.Mov(
table->AddSequence(OPCODE_STORE_CONTEXT, [](X64Emitter& e, Instr*& instr) {
/*lb.Mov(
LIRRegister(LIRRegisterType::REG64, LIRRegisterName::RCX),
instr->src1.offset,
instr->src2.value);
instr->src2.value);*/
UNIMPLEMENTED_SEQ();
instr = instr->next;
return true;
});
@ -262,24 +299,26 @@ void alloy::backend::x64::lowering::RegisterSequences(LoweringTable* table) {
// Memory
// --------------------------------------------------------------------------
table->AddSequence(OPCODE_LOAD, [](LIRBuilder& lb, Instr*& instr) {
table->AddSequence(OPCODE_LOAD, [](X64Emitter& e, Instr*& instr) {
// TODO(benvanik): dynamic register access check
// mov reg, [membase + address.32]
// TODO(benvanik): special for f32/f64/v128
UNIMPLEMENTED_SEQ();
instr = instr->next;
return true;
});
table->AddSequence(OPCODE_STORE, [](LIRBuilder& lb, Instr*& instr) {
table->AddSequence(OPCODE_STORE, [](X64Emitter& e, Instr*& instr) {
// TODO(benvanik): dynamic register access check
// mov [membase + address.32], reg
// TODO(benvanik): special for f32/f64/v128
UNIMPLEMENTED_SEQ();
instr = instr->next;
return true;
});
table->AddSequence(OPCODE_PREFETCH, [](LIRBuilder& lb, Instr*& instr) {
// TODO
table->AddSequence(OPCODE_PREFETCH, [](X64Emitter& e, Instr*& instr) {
UNIMPLEMENTED_SEQ();
instr = instr->next;
return true;
});
@ -288,134 +327,140 @@ void alloy::backend::x64::lowering::RegisterSequences(LoweringTable* table) {
// Comparisons
// --------------------------------------------------------------------------
table->AddSequence(OPCODE_MAX, [](LIRBuilder& lb, Instr*& instr) {
// TODO
table->AddSequence(OPCODE_MAX, [](X64Emitter& e, Instr*& instr) {
UNIMPLEMENTED_SEQ();
instr = instr->next;
return true;
});
table->AddSequence(OPCODE_MIN, [](LIRBuilder& lb, Instr*& instr) {
// TODO
table->AddSequence(OPCODE_MIN, [](X64Emitter& e, Instr*& instr) {
UNIMPLEMENTED_SEQ();
instr = instr->next;
return true;
});
table->AddSequence(OPCODE_SELECT, [](LIRBuilder& lb, Instr*& instr) {
// TODO
table->AddSequence(OPCODE_SELECT, [](X64Emitter& e, Instr*& instr) {
UNIMPLEMENTED_SEQ();
instr = instr->next;
return true;
});
table->AddSequence(OPCODE_IS_TRUE, [](LIRBuilder& lb, Instr*& instr) {
// TODO
table->AddSequence(OPCODE_IS_TRUE, [](X64Emitter& e, Instr*& instr) {
UNIMPLEMENTED_SEQ();
instr = instr->next;
return true;
});
table->AddSequence(OPCODE_IS_FALSE, [](LIRBuilder& lb, Instr*& instr) {
// TODO
table->AddSequence(OPCODE_IS_FALSE, [](X64Emitter& e, Instr*& instr) {
UNIMPLEMENTED_SEQ();
instr = instr->next;
return true;
});
table->AddSequence(OPCODE_COMPARE_EQ, [](LIRBuilder& lb, Instr*& instr) {
// TODO
table->AddSequence(OPCODE_COMPARE_EQ, [](X64Emitter& e, Instr*& instr) {
UNIMPLEMENTED_SEQ();
instr = instr->next;
return true;
});
table->AddSequence(OPCODE_COMPARE_NE, [](LIRBuilder& lb, Instr*& instr) {
// TODO
table->AddSequence(OPCODE_COMPARE_NE, [](X64Emitter& e, Instr*& instr) {
UNIMPLEMENTED_SEQ();
instr = instr->next;
return true;
});
table->AddSequence(OPCODE_COMPARE_SLT, [](LIRBuilder& lb, Instr*& instr) {
// TODO
table->AddSequence(OPCODE_COMPARE_SLT, [](X64Emitter& e, Instr*& instr) {
UNIMPLEMENTED_SEQ();
instr = instr->next;
return true;
});
table->AddSequence(OPCODE_COMPARE_SLE, [](LIRBuilder& lb, Instr*& instr) {
// TODO
table->AddSequence(OPCODE_COMPARE_SLE, [](X64Emitter& e, Instr*& instr) {
UNIMPLEMENTED_SEQ();
instr = instr->next;
return true;
});
table->AddSequence(OPCODE_COMPARE_SGT, [](LIRBuilder& lb, Instr*& instr) {
// TODO
table->AddSequence(OPCODE_COMPARE_SGT, [](X64Emitter& e, Instr*& instr) {
UNIMPLEMENTED_SEQ();
instr = instr->next;
return true;
});
table->AddSequence(OPCODE_COMPARE_SGE, [](LIRBuilder& lb, Instr*& instr) {
// TODO
table->AddSequence(OPCODE_COMPARE_SGE, [](X64Emitter& e, Instr*& instr) {
UNIMPLEMENTED_SEQ();
instr = instr->next;
return true;
});
table->AddSequence(OPCODE_COMPARE_ULT, [](LIRBuilder& lb, Instr*& instr) {
// TODO
table->AddSequence(OPCODE_COMPARE_ULT, [](X64Emitter& e, Instr*& instr) {
UNIMPLEMENTED_SEQ();
instr = instr->next;
return true;
});
table->AddSequence(OPCODE_COMPARE_ULE, [](LIRBuilder& lb, Instr*& instr) {
// TODO
table->AddSequence(OPCODE_COMPARE_ULE, [](X64Emitter& e, Instr*& instr) {
UNIMPLEMENTED_SEQ();
instr = instr->next;
return true;
});
table->AddSequence(OPCODE_COMPARE_UGT, [](LIRBuilder& lb, Instr*& instr) {
// TODO
table->AddSequence(OPCODE_COMPARE_UGT, [](X64Emitter& e, Instr*& instr) {
UNIMPLEMENTED_SEQ();
instr = instr->next;
return true;
});
table->AddSequence(OPCODE_COMPARE_UGE, [](LIRBuilder& lb, Instr*& instr) {
// TODO
table->AddSequence(OPCODE_COMPARE_UGE, [](X64Emitter& e, Instr*& instr) {
UNIMPLEMENTED_SEQ();
instr = instr->next;
return true;
});
table->AddSequence(OPCODE_DID_CARRY, [](LIRBuilder& lb, Instr*& instr) {
// TODO
table->AddSequence(OPCODE_DID_CARRY, [](X64Emitter& e, Instr*& instr) {
UNIMPLEMENTED_SEQ();
instr = instr->next;
return true;
});
table->AddSequence(OPCODE_DID_OVERFLOW, [](LIRBuilder& lb, Instr*& instr) {
// TODO
table->AddSequence(OPCODE_DID_OVERFLOW, [](X64Emitter& e, Instr*& instr) {
UNIMPLEMENTED_SEQ();
instr = instr->next;
return true;
});
table->AddSequence(OPCODE_VECTOR_COMPARE_EQ, [](LIRBuilder& lb, Instr*& instr) {
// TODO
table->AddSequence(OPCODE_DID_SATURATE, [](X64Emitter& e, Instr*& instr) {
UNIMPLEMENTED_SEQ();
instr = instr->next;
return true;
});
table->AddSequence(OPCODE_VECTOR_COMPARE_SGT, [](LIRBuilder& lb, Instr*& instr) {
// TODO
table->AddSequence(OPCODE_VECTOR_COMPARE_EQ, [](X64Emitter& e, Instr*& instr) {
UNIMPLEMENTED_SEQ();
instr = instr->next;
return true;
});
table->AddSequence(OPCODE_VECTOR_COMPARE_SGE, [](LIRBuilder& lb, Instr*& instr) {
// TODO
table->AddSequence(OPCODE_VECTOR_COMPARE_SGT, [](X64Emitter& e, Instr*& instr) {
UNIMPLEMENTED_SEQ();
instr = instr->next;
return true;
});
table->AddSequence(OPCODE_VECTOR_COMPARE_UGT, [](LIRBuilder& lb, Instr*& instr) {
// TODO
table->AddSequence(OPCODE_VECTOR_COMPARE_SGE, [](X64Emitter& e, Instr*& instr) {
UNIMPLEMENTED_SEQ();
instr = instr->next;
return true;
});
table->AddSequence(OPCODE_VECTOR_COMPARE_UGE, [](LIRBuilder& lb, Instr*& instr) {
// TODO
table->AddSequence(OPCODE_VECTOR_COMPARE_UGT, [](X64Emitter& e, Instr*& instr) {
UNIMPLEMENTED_SEQ();
instr = instr->next;
return true;
});
table->AddSequence(OPCODE_VECTOR_COMPARE_UGE, [](X64Emitter& e, Instr*& instr) {
UNIMPLEMENTED_SEQ();
instr = instr->next;
return true;
});
@ -424,200 +469,218 @@ void alloy::backend::x64::lowering::RegisterSequences(LoweringTable* table) {
// Math
// --------------------------------------------------------------------------
table->AddSequence(OPCODE_ADD, [](LIRBuilder& lb, Instr*& instr) {
// TODO
table->AddSequence(OPCODE_ADD, [](X64Emitter& e, Instr*& instr) {
UNIMPLEMENTED_SEQ();
instr = instr->next;
return true;
});
table->AddSequence(OPCODE_ADD_CARRY, [](LIRBuilder& lb, Instr*& instr) {
// TODO
table->AddSequence(OPCODE_ADD_CARRY, [](X64Emitter& e, Instr*& instr) {
UNIMPLEMENTED_SEQ();
instr = instr->next;
return true;
});
table->AddSequence(OPCODE_SUB, [](LIRBuilder& lb, Instr*& instr) {
// TODO
table->AddSequence(OPCODE_SUB, [](X64Emitter& e, Instr*& instr) {
UNIMPLEMENTED_SEQ();
instr = instr->next;
return true;
});
table->AddSequence(OPCODE_MUL, [](LIRBuilder& lb, Instr*& instr) {
// TODO
table->AddSequence(OPCODE_MUL, [](X64Emitter& e, Instr*& instr) {
UNIMPLEMENTED_SEQ();
instr = instr->next;
return true;
});
table->AddSequence(OPCODE_DIV, [](LIRBuilder& lb, Instr*& instr) {
// TODO
table->AddSequence(OPCODE_MUL_HI, [](X64Emitter& e, Instr*& instr) {
UNIMPLEMENTED_SEQ();
instr = instr->next;
return true;
});
table->AddSequence(OPCODE_MUL_ADD, [](LIRBuilder& lb, Instr*& instr) {
// TODO
table->AddSequence(OPCODE_DIV, [](X64Emitter& e, Instr*& instr) {
UNIMPLEMENTED_SEQ();
instr = instr->next;
return true;
});
table->AddSequence(OPCODE_MUL_SUB, [](LIRBuilder& lb, Instr*& instr) {
// TODO
table->AddSequence(OPCODE_MUL_ADD, [](X64Emitter& e, Instr*& instr) {
UNIMPLEMENTED_SEQ();
instr = instr->next;
return true;
});
table->AddSequence(OPCODE_NEG, [](LIRBuilder& lb, Instr*& instr) {
// TODO
table->AddSequence(OPCODE_MUL_SUB, [](X64Emitter& e, Instr*& instr) {
UNIMPLEMENTED_SEQ();
instr = instr->next;
return true;
});
table->AddSequence(OPCODE_ABS, [](LIRBuilder& lb, Instr*& instr) {
// TODO
table->AddSequence(OPCODE_NEG, [](X64Emitter& e, Instr*& instr) {
UNIMPLEMENTED_SEQ();
instr = instr->next;
return true;
});
table->AddSequence(OPCODE_SQRT, [](LIRBuilder& lb, Instr*& instr) {
// TODO
table->AddSequence(OPCODE_ABS, [](X64Emitter& e, Instr*& instr) {
UNIMPLEMENTED_SEQ();
instr = instr->next;
return true;
});
table->AddSequence(OPCODE_RSQRT, [](LIRBuilder& lb, Instr*& instr) {
// TODO
table->AddSequence(OPCODE_SQRT, [](X64Emitter& e, Instr*& instr) {
UNIMPLEMENTED_SEQ();
instr = instr->next;
return true;
});
table->AddSequence(OPCODE_POW2, [](LIRBuilder& lb, Instr*& instr) {
// TODO
table->AddSequence(OPCODE_RSQRT, [](X64Emitter& e, Instr*& instr) {
UNIMPLEMENTED_SEQ();
instr = instr->next;
return true;
});
table->AddSequence(OPCODE_LOG2, [](LIRBuilder& lb, Instr*& instr) {
// TODO
table->AddSequence(OPCODE_POW2, [](X64Emitter& e, Instr*& instr) {
UNIMPLEMENTED_SEQ();
instr = instr->next;
return true;
});
table->AddSequence(OPCODE_DOT_PRODUCT_3, [](LIRBuilder& lb, Instr*& instr) {
// TODO
table->AddSequence(OPCODE_LOG2, [](X64Emitter& e, Instr*& instr) {
UNIMPLEMENTED_SEQ();
instr = instr->next;
return true;
});
table->AddSequence(OPCODE_DOT_PRODUCT_4, [](LIRBuilder& lb, Instr*& instr) {
// TODO
table->AddSequence(OPCODE_DOT_PRODUCT_3, [](X64Emitter& e, Instr*& instr) {
UNIMPLEMENTED_SEQ();
instr = instr->next;
return true;
});
table->AddSequence(OPCODE_AND, [](LIRBuilder& lb, Instr*& instr) {
// TODO
table->AddSequence(OPCODE_DOT_PRODUCT_4, [](X64Emitter& e, Instr*& instr) {
UNIMPLEMENTED_SEQ();
instr = instr->next;
return true;
});
table->AddSequence(OPCODE_OR, [](LIRBuilder& lb, Instr*& instr) {
// TODO
table->AddSequence(OPCODE_AND, [](X64Emitter& e, Instr*& instr) {
UNIMPLEMENTED_SEQ();
instr = instr->next;
return true;
});
table->AddSequence(OPCODE_XOR, [](LIRBuilder& lb, Instr*& instr) {
// TODO
table->AddSequence(OPCODE_OR, [](X64Emitter& e, Instr*& instr) {
UNIMPLEMENTED_SEQ();
instr = instr->next;
return true;
});
table->AddSequence(OPCODE_NOT, [](LIRBuilder& lb, Instr*& instr) {
// TODO
table->AddSequence(OPCODE_XOR, [](X64Emitter& e, Instr*& instr) {
UNIMPLEMENTED_SEQ();
instr = instr->next;
return true;
});
table->AddSequence(OPCODE_SHL, [](LIRBuilder& lb, Instr*& instr) {
// TODO
table->AddSequence(OPCODE_NOT, [](X64Emitter& e, Instr*& instr) {
UNIMPLEMENTED_SEQ();
instr = instr->next;
return true;
});
table->AddSequence(OPCODE_VECTOR_SHL, [](LIRBuilder& lb, Instr*& instr) {
// TODO
table->AddSequence(OPCODE_SHL, [](X64Emitter& e, Instr*& instr) {
UNIMPLEMENTED_SEQ();
instr = instr->next;
return true;
});
table->AddSequence(OPCODE_SHR, [](LIRBuilder& lb, Instr*& instr) {
// TODO
table->AddSequence(OPCODE_VECTOR_SHL, [](X64Emitter& e, Instr*& instr) {
UNIMPLEMENTED_SEQ();
instr = instr->next;
return true;
});
table->AddSequence(OPCODE_VECTOR_SHR, [](LIRBuilder& lb, Instr*& instr) {
// TODO
table->AddSequence(OPCODE_SHR, [](X64Emitter& e, Instr*& instr) {
UNIMPLEMENTED_SEQ();
instr = instr->next;
return true;
});
table->AddSequence(OPCODE_SHA, [](LIRBuilder& lb, Instr*& instr) {
// TODO
table->AddSequence(OPCODE_VECTOR_SHR, [](X64Emitter& e, Instr*& instr) {
UNIMPLEMENTED_SEQ();
instr = instr->next;
return true;
});
table->AddSequence(OPCODE_VECTOR_SHA, [](LIRBuilder& lb, Instr*& instr) {
// TODO
table->AddSequence(OPCODE_SHA, [](X64Emitter& e, Instr*& instr) {
UNIMPLEMENTED_SEQ();
instr = instr->next;
return true;
});
table->AddSequence(OPCODE_ROTATE_LEFT, [](LIRBuilder& lb, Instr*& instr) {
// TODO
table->AddSequence(OPCODE_VECTOR_SHA, [](X64Emitter& e, Instr*& instr) {
UNIMPLEMENTED_SEQ();
instr = instr->next;
return true;
});
table->AddSequence(OPCODE_BYTE_SWAP, [](LIRBuilder& lb, Instr*& instr) {
// TODO
table->AddSequence(OPCODE_ROTATE_LEFT, [](X64Emitter& e, Instr*& instr) {
UNIMPLEMENTED_SEQ();
instr = instr->next;
return true;
});
table->AddSequence(OPCODE_CNTLZ, [](LIRBuilder& lb, Instr*& instr) {
// TODO
table->AddSequence(OPCODE_BYTE_SWAP, [](X64Emitter& e, Instr*& instr) {
UNIMPLEMENTED_SEQ();
instr = instr->next;
return true;
});
table->AddSequence(OPCODE_INSERT, [](LIRBuilder& lb, Instr*& instr) {
// TODO
table->AddSequence(OPCODE_CNTLZ, [](X64Emitter& e, Instr*& instr) {
UNIMPLEMENTED_SEQ();
instr = instr->next;
return true;
});
table->AddSequence(OPCODE_EXTRACT, [](LIRBuilder& lb, Instr*& instr) {
// TODO
table->AddSequence(OPCODE_INSERT, [](X64Emitter& e, Instr*& instr) {
UNIMPLEMENTED_SEQ();
instr = instr->next;
return true;
});
table->AddSequence(OPCODE_SPLAT, [](LIRBuilder& lb, Instr*& instr) {
// TODO
table->AddSequence(OPCODE_EXTRACT, [](X64Emitter& e, Instr*& instr) {
UNIMPLEMENTED_SEQ();
instr = instr->next;
return true;
});
table->AddSequence(OPCODE_PERMUTE, [](LIRBuilder& lb, Instr*& instr) {
// TODO
table->AddSequence(OPCODE_SPLAT, [](X64Emitter& e, Instr*& instr) {
UNIMPLEMENTED_SEQ();
instr = instr->next;
return true;
});
table->AddSequence(OPCODE_SWIZZLE, [](LIRBuilder& lb, Instr*& instr) {
// TODO
table->AddSequence(OPCODE_PERMUTE, [](X64Emitter& e, Instr*& instr) {
UNIMPLEMENTED_SEQ();
instr = instr->next;
return true;
});
table->AddSequence(OPCODE_SWIZZLE, [](X64Emitter& e, Instr*& instr) {
UNIMPLEMENTED_SEQ();
instr = instr->next;
return true;
});
table->AddSequence(OPCODE_PACK, [](X64Emitter& e, Instr*& instr) {
UNIMPLEMENTED_SEQ();
instr = instr->next;
return true;
});
table->AddSequence(OPCODE_UNPACK, [](X64Emitter& e, Instr*& instr) {
UNIMPLEMENTED_SEQ();
instr = instr->next;
return true;
});
@ -626,26 +689,26 @@ void alloy::backend::x64::lowering::RegisterSequences(LoweringTable* table) {
// Atomic
// --------------------------------------------------------------------------
table->AddSequence(OPCODE_COMPARE_EXCHANGE, [](LIRBuilder& lb, Instr*& instr) {
// TODO
table->AddSequence(OPCODE_COMPARE_EXCHANGE, [](X64Emitter& e, Instr*& instr) {
UNIMPLEMENTED_SEQ();
instr = instr->next;
return true;
});
table->AddSequence(OPCODE_ATOMIC_EXCHANGE, [](LIRBuilder& lb, Instr*& instr) {
// TODO
table->AddSequence(OPCODE_ATOMIC_EXCHANGE, [](X64Emitter& e, Instr*& instr) {
UNIMPLEMENTED_SEQ();
instr = instr->next;
return true;
});
table->AddSequence(OPCODE_ATOMIC_ADD, [](LIRBuilder& lb, Instr*& instr) {
// TODO
table->AddSequence(OPCODE_ATOMIC_ADD, [](X64Emitter& e, Instr*& instr) {
UNIMPLEMENTED_SEQ();
instr = instr->next;
return true;
});
table->AddSequence(OPCODE_ATOMIC_SUB, [](LIRBuilder& lb, Instr*& instr) {
// TODO
table->AddSequence(OPCODE_ATOMIC_SUB, [](X64Emitter& e, Instr*& instr) {
UNIMPLEMENTED_SEQ();
instr = instr->next;
return true;
});

View File

@ -45,59 +45,25 @@ void LoweringTable::AddSequence(hir::Opcode starting_opcode, sequence_fn_t fn) {
lookup_[starting_opcode] = new_entry;
}
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) {
auto lir_label = lir_builder->NewLabel(hir_label->name);
hir_label->tag = lir_label;
hir_label = hir_label->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 entry = lookup_[hir_instr->opcode->num];
while (entry) {
if ((*entry->fn)(*lir_builder, hir_instr)) {
processed = true;
break;
}
entry = entry->next;
}
if (!processed) {
// No sequence found!
XELOGE("Unable to process HIR opcode %s", hir_instr->opcode->name);
return 1;
hir_instr = hir_instr->next;
int LoweringTable::ProcessBlock(X64Emitter& e, hir::Block* block) {
// Process instructions.
auto instr = block->instr_head;
while (instr) {
bool processed = false;
auto entry = lookup_[instr->opcode->num];
while (entry) {
if ((*entry->fn)(e, instr)) {
processed = true;
break;
}
entry = entry->next;
}
if (!processed) {
// No sequence found!
XELOGE("Unable to process HIR opcode %s", instr->opcode->name);
return 1;
instr = instr->next;
}
lir_builder->EndBlock();
hir_block = hir_block->next;
}
return 0;

View File

@ -11,8 +11,6 @@
#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/hir_builder.h>
@ -20,6 +18,7 @@ namespace alloy {
namespace backend {
namespace x64 {
class X64Backend;
class X64Emitter;
namespace lowering {
@ -30,10 +29,10 @@ public:
int Initialize();
int Process(hir::HIRBuilder* hir_builder, lir::LIRBuilder* lir_builder);
int ProcessBlock(X64Emitter& e, hir::Block* block);
public:
typedef bool(*sequence_fn_t)(lir::LIRBuilder& lb, hir::Instr*& instr);
typedef bool(*sequence_fn_t)(X64Emitter& e, hir::Instr*& instr);
void AddSequence(hir::Opcode starting_opcode, sequence_fn_t fn);
private:
@ -43,6 +42,8 @@ private:
sequence_fn_entry_t* next;
};
// NOTE: this class is shared by multiple threads and is not thread safe.
// Do not modify anything after init.
X64Backend* backend_;
sequence_fn_entry_t* lookup_[hir::__OPCODE_MAX_VALUE];
};

View File

@ -1,58 +0,0 @@
/**
******************************************************************************
* 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. *
******************************************************************************
*/
#include <alloy/backend/x64/optimizer/optimizer.h>
#include <alloy/backend/x64/tracing.h>
#include <alloy/backend/x64/optimizer/optimizer_pass.h>
using namespace alloy;
using namespace alloy::backend::x64::lir;
using namespace alloy::backend::x64::optimizer;
using namespace alloy::runtime;
Optimizer::Optimizer(Runtime* runtime) :
runtime_(runtime) {
alloy::tracing::WriteEvent(EventType::Init({
}));
}
Optimizer::~Optimizer() {
Reset();
for (auto it = passes_.begin(); it != passes_.end(); ++it) {
OptimizerPass* pass = *it;
delete pass;
}
alloy::tracing::WriteEvent(EventType::Deinit({
}));
}
void Optimizer::AddPass(OptimizerPass* pass) {
pass->Initialize(this);
passes_.push_back(pass);
}
void Optimizer::Reset() {
}
int Optimizer::Optimize(LIRBuilder* builder) {
// TODO(benvanik): sophisticated stuff. Run passes in parallel, run until they
// stop changing things, etc.
for (auto it = passes_.begin(); it != passes_.end(); ++it) {
OptimizerPass* pass = *it;
if (pass->Run(builder)) {
return 1;
}
}
return 0;
}

View File

@ -1,54 +0,0 @@
/**
******************************************************************************
* 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_OPTIMIZER_OPTIMIZER_H_
#define ALLOY_BACKEND_X64_OPTIMIZER_OPTIMIZER_H_
#include <alloy/core.h>
#include <alloy/backend/x64/lir/lir_builder.h>
namespace alloy { namespace runtime { class Runtime; } }
namespace alloy {
namespace backend {
namespace x64 {
namespace optimizer {
class OptimizerPass;
class Optimizer {
public:
Optimizer(runtime::Runtime* runtime);
~Optimizer();
runtime::Runtime* runtime() const { return runtime_; }
void AddPass(OptimizerPass* pass);
void Reset();
int Optimize(lir::LIRBuilder* builder);
private:
runtime::Runtime* runtime_;
typedef std::vector<OptimizerPass*> PassList;
PassList passes_;
};
} // namespace optimizer
} // namespace x64
} // namespace backend
} // namespace alloy
#endif // ALLOY_BACKEND_X64_OPTIMIZER_OPTIMIZER_H_

View File

@ -1,29 +0,0 @@
/**
******************************************************************************
* 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. *
******************************************************************************
*/
#include <alloy/backend/x64/optimizer/optimizer_pass.h>
#include <alloy/backend/x64/optimizer/optimizer.h>
using namespace alloy;
using namespace alloy::backend::x64::optimizer;
OptimizerPass::OptimizerPass() :
runtime_(0), optimizer_(0) {
}
OptimizerPass::~OptimizerPass() {
}
int OptimizerPass::Initialize(Optimizer* optimizer) {
runtime_ = optimizer->runtime();
optimizer_ = optimizer;
return 0;
}

View File

@ -1,49 +0,0 @@
/**
******************************************************************************
* 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_OPTIMIZER_OPTIMIZER_PASS_H_
#define ALLOY_BACKEND_X64_OPTIMIZER_OPTIMIZER_PASS_H_
#include <alloy/core.h>
#include <alloy/backend/x64/lir/lir_builder.h>
namespace alloy { namespace runtime { class Runtime; } }
namespace alloy {
namespace backend {
namespace x64 {
namespace optimizer {
class Optimizer;
class OptimizerPass {
public:
OptimizerPass();
virtual ~OptimizerPass();
virtual int Initialize(Optimizer* optimizer);
virtual int Run(lir::LIRBuilder* builder) = 0;
protected:
runtime::Runtime* runtime_;
Optimizer* optimizer_;
};
} // namespace optimizer
} // namespace x64
} // namespace backend
} // namespace alloy
#endif // ALLOY_BACKEND_X64_OPTIMIZER_OPTIMIZER_PASS_H_

View File

@ -1,17 +0,0 @@
/**
******************************************************************************
* 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_OPTIMIZER_PASSES_H_
#define ALLOY_BACKEND_X64_OPTIMIZER_PASSES_H_
#include <alloy/backend/x64/optimizer/passes/reachability_pass.h>
#include <alloy/backend/x64/optimizer/passes/redundant_mov_pass.h>
#include <alloy/backend/x64/optimizer/passes/register_allocation_pass.h>
#endif // ALLOY_BACKEND_X64_OPTIMIZER_PASSES_H_

View File

@ -1,49 +0,0 @@
/**
******************************************************************************
* 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. *
******************************************************************************
*/
#include <alloy/backend/x64/optimizer/passes/reachability_pass.h>
using namespace alloy;
using namespace alloy::backend::x64::lir;
using namespace alloy::backend::x64::optimizer;
using namespace alloy::backend::x64::optimizer::passes;
ReachabilityPass::ReachabilityPass() :
OptimizerPass() {
}
ReachabilityPass::~ReachabilityPass() {
}
int ReachabilityPass::Run(LIRBuilder* builder) {
// Run through blocks. If blocks have no incoming edges remove them.
// Afterwards, remove any unneeded jumps (jumping to the next block).
// TODO(benvanik): dead block removal.
// Remove unneeded jumps.
auto block = builder->first_block();
while (block) {
auto tail = block->instr_tail;
if (tail && tail->opcode == &LIR_OPCODE_JUMP_info) {
// Jump. Check target.
if (tail->arg0_type() == LIROperandType::LABEL) {
auto target = *tail->arg0<LIRLabel*>();
if (target->block == block->next) {
// Jumping to subsequent block. Remove.
tail->Remove();
}
}
}
block = block->next;
}
return 0;
}

View File

@ -1,39 +0,0 @@
/**
******************************************************************************
* 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_OPTIMIZER_PASSES_REACHABILITY_PASS_H_
#define ALLOY_BACKEND_X64_OPTIMIZER_PASSES_REACHABILITY_PASS_H_
#include <alloy/backend/x64/optimizer/optimizer_pass.h>
namespace alloy {
namespace backend {
namespace x64 {
namespace optimizer {
namespace passes {
class ReachabilityPass : public OptimizerPass {
public:
ReachabilityPass();
virtual ~ReachabilityPass();
virtual int Run(lir::LIRBuilder* builder);
};
} // namespace passes
} // namespace optimizer
} // namespace x64
} // namespace backend
} // namespace alloy
#endif // ALLOY_BACKEND_X64_OPTIMIZER_PASSES_REACHABILITY_PASS_H_

View File

@ -1,27 +0,0 @@
/**
******************************************************************************
* 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. *
******************************************************************************
*/
#include <alloy/backend/x64/optimizer/passes/redundant_mov_pass.h>
using namespace alloy;
using namespace alloy::backend::x64::lir;
using namespace alloy::backend::x64::optimizer;
using namespace alloy::backend::x64::optimizer::passes;
RedundantMovPass::RedundantMovPass() :
OptimizerPass() {
}
RedundantMovPass::~RedundantMovPass() {
}
int RedundantMovPass::Run(LIRBuilder* builder) {
return 0;
}

View File

@ -1,39 +0,0 @@
/**
******************************************************************************
* 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_OPTIMIZER_PASSES_REDUNDANT_MOV_PASS_H_
#define ALLOY_BACKEND_X64_OPTIMIZER_PASSES_REDUNDANT_MOV_PASS_H_
#include <alloy/backend/x64/optimizer/optimizer_pass.h>
namespace alloy {
namespace backend {
namespace x64 {
namespace optimizer {
namespace passes {
class RedundantMovPass : public OptimizerPass {
public:
RedundantMovPass();
virtual ~RedundantMovPass();
virtual int Run(lir::LIRBuilder* builder);
};
} // namespace passes
} // namespace optimizer
} // namespace x64
} // namespace backend
} // namespace alloy
#endif // ALLOY_BACKEND_X64_OPTIMIZER_PASSES_REDUNDANT_MOV_PASS_H_

View File

@ -1,27 +0,0 @@
/**
******************************************************************************
* 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. *
******************************************************************************
*/
#include <alloy/backend/x64/optimizer/passes/register_allocation_pass.h>
using namespace alloy;
using namespace alloy::backend::x64::lir;
using namespace alloy::backend::x64::optimizer;
using namespace alloy::backend::x64::optimizer::passes;
RegisterAllocationPass::RegisterAllocationPass() :
OptimizerPass() {
}
RegisterAllocationPass::~RegisterAllocationPass() {
}
int RegisterAllocationPass::Run(LIRBuilder* builder) {
return 0;
}

View File

@ -1,39 +0,0 @@
/**
******************************************************************************
* 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_OPTIMIZER_PASSES_REGISTER_ALLOCATION_PASS_H_
#define ALLOY_BACKEND_X64_OPTIMIZER_PASSES_REGISTER_ALLOCATION_PASS_H_
#include <alloy/backend/x64/optimizer/optimizer_pass.h>
namespace alloy {
namespace backend {
namespace x64 {
namespace optimizer {
namespace passes {
class RegisterAllocationPass : public OptimizerPass {
public:
RegisterAllocationPass();
virtual ~RegisterAllocationPass();
virtual int Run(lir::LIRBuilder* builder);
};
} // namespace passes
} // namespace optimizer
} // namespace x64
} // namespace backend
} // namespace alloy
#endif // ALLOY_BACKEND_X64_OPTIMIZER_PASSES_REGISTER_ALLOCATION_PASS_H_

View File

@ -1,11 +0,0 @@
# Copyright 2013 Ben Vanik. All Rights Reserved.
{
'sources': [
'reachability_pass.cc',
'reachability_pass.h',
'redundant_mov_pass.cc',
'redundant_mov_pass.h',
'register_allocation_pass.cc',
'register_allocation_pass.h',
],
}

View File

@ -1,15 +0,0 @@
# Copyright 2013 Ben Vanik. All Rights Reserved.
{
'sources': [
'optimizer.cc',
'optimizer.h',
'optimizer_pass.cc',
'optimizer_pass.h',
'optimizer_passes.h',
'tracing.h',
],
'includes': [
'passes/sources.gypi',
],
}

View File

@ -1,47 +0,0 @@
/**
******************************************************************************
* 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_OPTIMIZER_TRACING_H_
#define ALLOY_BACKEND_X64_OPTIMIZER_TRACING_H_
#include <alloy/backend/x64/tracing.h>
namespace alloy {
namespace backend {
namespace x64 {
namespace optimizer {
const uint32_t ALLOY_BACKEND_X64_OPTIMIZER =
alloy::backend::x64::EventType::ALLOY_BACKEND_X64_OPTIMIZER;
class EventType {
public:
enum {
ALLOY_BACKEND_X64_OPTIMIZER_INIT = ALLOY_BACKEND_X64_OPTIMIZER | (1),
ALLOY_BACKEND_X64_OPTIMIZER_DEINIT = ALLOY_BACKEND_X64_OPTIMIZER | (2),
};
typedef struct {
static const uint32_t event_type = ALLOY_BACKEND_X64_OPTIMIZER_INIT;
} Init;
typedef struct {
static const uint32_t event_type = ALLOY_BACKEND_X64_OPTIMIZER_DEINIT;
} Deinit;
};
} // namespace optimizer
} // namespace x64
} // namespace backend
} // namespace alloy
#endif // ALLOY_BACKEND_X64_OPTIMIZER_TRACING_H_

View File

@ -15,8 +15,6 @@
],
'includes': [
'lir/sources.gypi',
'lowering/sources.gypi',
'optimizer/sources.gypi',
],
}

View File

@ -30,9 +30,6 @@ public:
ALLOY_BACKEND_X64_ASSEMBLER = ALLOY_BACKEND_X64 | (1 << 20),
ALLOY_BACKEND_X64_ASSEMBLER_INIT = ALLOY_BACKEND_X64_ASSEMBLER | (1),
ALLOY_BACKEND_X64_ASSEMBLER_DEINIT = ALLOY_BACKEND_X64_ASSEMBLER | (2),
ALLOY_BACKEND_X64_LIR = ALLOY_BACKEND_X64 | (2 << 20),
ALLOY_BACKEND_X64_OPTIMIZER = ALLOY_BACKEND_X64 | (3 << 20),
};
typedef struct {

View File

@ -13,10 +13,6 @@
#include <alloy/backend/x64/x64_backend.h>
#include <alloy/backend/x64/x64_emitter.h>
#include <alloy/backend/x64/x64_function.h>
#include <alloy/backend/x64/lir/lir_builder.h>
#include <alloy/backend/x64/lowering/lowering_table.h>
#include <alloy/backend/x64/optimizer/optimizer.h>
#include <alloy/backend/x64/optimizer/optimizer_passes.h>
#include <alloy/hir/hir_builder.h>
#include <alloy/hir/label.h>
#include <alloy/runtime/runtime.h>
@ -28,16 +24,12 @@ namespace BE {
using namespace alloy;
using namespace alloy::backend;
using namespace alloy::backend::x64;
using namespace alloy::backend::x64::lir;
using namespace alloy::backend::x64::optimizer;
using namespace alloy::hir;
using namespace alloy::runtime;
X64Assembler::X64Assembler(X64Backend* backend) :
x64_backend_(backend),
builder_(0),
optimizer_(0),
emitter_(0),
Assembler(backend) {
}
@ -47,8 +39,6 @@ X64Assembler::~X64Assembler() {
}));
delete emitter_;
delete optimizer_;
delete builder_;
}
int X64Assembler::Initialize() {
@ -57,14 +47,8 @@ int X64Assembler::Initialize() {
return result;
}
builder_ = new LIRBuilder(x64_backend_);
optimizer_ = new Optimizer(backend_->runtime());
optimizer_->AddPass(new passes::RegisterAllocationPass());
optimizer_->AddPass(new passes::RedundantMovPass());
optimizer_->AddPass(new passes::ReachabilityPass());
emitter_ = new X64Emitter(x64_backend_);
emitter_ = new X64Emitter(x64_backend_,
new XbyakAllocator());
alloy::tracing::WriteEvent(EventType::AssemblerInit({
}));
@ -73,45 +57,20 @@ int X64Assembler::Initialize() {
}
void X64Assembler::Reset() {
builder_->Reset();
optimizer_->Reset();
string_buffer_.Reset();
Assembler::Reset();
}
int X64Assembler::Assemble(
FunctionInfo* symbol_info, HIRBuilder* hir_builder,
FunctionInfo* symbol_info, HIRBuilder* builder,
uint32_t debug_info_flags, DebugInfo* debug_info,
Function** out_function) {
int result = 0;
// Lower HIR -> LIR.
auto lowering_table = x64_backend_->lowering_table();
result = lowering_table->Process(hir_builder, builder_);
XEEXPECTZERO(result);
// Stash raw LIR.
if (debug_info_flags & DEBUG_INFO_RAW_LIR_DISASM) {
builder_->Dump(&string_buffer_);
debug_info->set_raw_lir_disasm(string_buffer_.ToString());
string_buffer_.Reset();
}
// Optimize LIR.
result = optimizer_->Optimize(builder_);
XEEXPECTZERO(result);
// Stash optimized LIR.
if (debug_info_flags & DEBUG_INFO_LIR_DISASM) {
builder_->Dump(&string_buffer_);
debug_info->set_lir_disasm(string_buffer_.ToString());
string_buffer_.Reset();
}
// Emit machine code.
// Lower HIR -> x64.
void* machine_code = 0;
size_t code_size = 0;
result = emitter_->Emit(builder_, machine_code, code_size);
result = emitter_->Emit(builder, machine_code, code_size);
XEEXPECTZERO(result);
// Stash generated machine code.

View File

@ -21,8 +21,6 @@ namespace x64 {
class X64Backend;
class X64Emitter;
namespace lir { class LIRBuilder; }
namespace optimizer { class Optimizer; }
class X64Assembler : public Assembler {
@ -44,8 +42,6 @@ private:
private:
X64Backend* x64_backend_;
lir::LIRBuilder* builder_;
optimizer::Optimizer* optimizer_;
X64Emitter* emitter_;
StringBuffer string_buffer_;

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;
}

View File

@ -12,6 +12,9 @@
#include <alloy/core.h>
#include <third_party/xbyak/xbyak/xbyak.h>
XEDECLARECLASS2(alloy, hir, HIRBuilder);
namespace alloy {
namespace backend {
@ -19,26 +22,31 @@ namespace x64 {
class X64Backend;
class X64CodeCache;
namespace lir { class LIRBuilder; }
class XbyakAllocator;
class XbyakGenerator;
class X64Emitter {
// Unfortunately due to the design of xbyak we have to pass this to the ctor.
class XbyakAllocator : public Xbyak::Allocator {
public:
X64Emitter(X64Backend* backend);
~X64Emitter();
virtual bool useProtect() const { return false; }
};
class X64Emitter : public Xbyak::CodeGenerator {
public:
X64Emitter(X64Backend* backend, XbyakAllocator* allocator);
virtual ~X64Emitter();
int Initialize();
int Emit(lir::LIRBuilder* builder,
int Emit(hir::HIRBuilder* builder,
void*& out_code_address, size_t& out_code_size);
private:
void* Emplace(X64CodeCache* code_cache);
int Emit(hir::HIRBuilder* builder);
private:
X64Backend* backend_;
X64CodeCache* code_cache_;
XbyakAllocator* allocator_;
XbyakGenerator* generator_;
};

View File

@ -13,6 +13,8 @@
#include <alloy/compiler/passes/constant_propagation_pass.h>
#include <alloy/compiler/passes/context_promotion_pass.h>
#include <alloy/compiler/passes/dead_code_elimination_pass.h>
#include <alloy/compiler/passes/finalization_pass.h>
#include <alloy/compiler/passes/register_allocation_pass.h>
//#include <alloy/compiler/passes/dead_store_elimination_pass.h>
#include <alloy/compiler/passes/simplification_pass.h>

View File

@ -0,0 +1,58 @@
/**
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2014 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#include <alloy/compiler/passes/finalization_pass.h>
#include <alloy/backend/backend.h>
#include <alloy/compiler/compiler.h>
#include <alloy/runtime/runtime.h>
using namespace alloy;
using namespace alloy::backend;
using namespace alloy::compiler;
using namespace alloy::compiler::passes;
using namespace alloy::frontend;
using namespace alloy::hir;
using namespace alloy::runtime;
FinalizationPass::FinalizationPass() :
CompilerPass() {
}
FinalizationPass::~FinalizationPass() {
}
int FinalizationPass::Run(HIRBuilder* builder) {
// Process the HIR and prepare it for lowering.
// After this is done the HIR should be ready for emitting.
auto arena = builder->arena();
auto block = builder->first_block();
while (block) {
// Ensure all labels have names.
auto label = block->label_head;
while (label) {
if (!label->name) {
char* name = (char*)arena->Alloc(6 + 4 + 1);
xestrcpya(name, 6 + 1, "_label");
char* part = _itoa(label->id, name + 6, 10);
label->name = name;
}
label = label->next;
}
// ?
block = block->next;
}
return 0;
}

View File

@ -0,0 +1,37 @@
/**
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2014 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#ifndef ALLOY_COMPILER_PASSES_FINALIZATION_PASS_H_
#define ALLOY_COMPILER_PASSES_FINALIZATION_PASS_H_
#include <alloy/compiler/compiler_pass.h>
namespace alloy {
namespace compiler {
namespace passes {
class FinalizationPass : public CompilerPass {
public:
FinalizationPass();
virtual ~FinalizationPass();
virtual int Run(hir::HIRBuilder* builder);
private:
};
} // namespace passes
} // namespace compiler
} // namespace alloy
#endif // ALLOY_COMPILER_PASSES_FINALIZATION_PASS_H_

View File

@ -0,0 +1,51 @@
/**
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2014 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#include <alloy/compiler/passes/register_allocation_pass.h>
#include <alloy/backend/backend.h>
#include <alloy/compiler/compiler.h>
#include <alloy/runtime/runtime.h>
using namespace alloy;
using namespace alloy::backend;
using namespace alloy::compiler;
using namespace alloy::compiler::passes;
using namespace alloy::frontend;
using namespace alloy::hir;
using namespace alloy::runtime;
RegisterAllocationPass::RegisterAllocationPass(Backend* backend) :
CompilerPass() {
// TODO(benvanik): query backend info (register layout, etc).
}
RegisterAllocationPass::~RegisterAllocationPass() {
}
int RegisterAllocationPass::Run(HIRBuilder* builder) {
// Run through each block and give each dest value a register.
// This pass is currently really dumb, and will over spill and other badness.
auto block = builder->first_block();
while (block) {
if (ProcessBlock(block)) {
return 1;
}
block = block->next;
}
return 0;
}
int RegisterAllocationPass::ProcessBlock(Block* block) {
//
return 0;
}

View File

@ -0,0 +1,40 @@
/**
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2014 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#ifndef ALLOY_COMPILER_PASSES_REGISTER_ALLOCATION_PASS_H_
#define ALLOY_COMPILER_PASSES_REGISTER_ALLOCATION_PASS_H_
#include <alloy/compiler/compiler_pass.h>
XEDECLARECLASS2(alloy, backend, Backend);
namespace alloy {
namespace compiler {
namespace passes {
class RegisterAllocationPass : public CompilerPass {
public:
RegisterAllocationPass(backend::Backend* backend);
virtual ~RegisterAllocationPass();
virtual int Run(hir::HIRBuilder* builder);
private:
int ProcessBlock(hir::Block* block);
};
} // namespace passes
} // namespace compiler
} // namespace alloy
#endif // ALLOY_COMPILER_PASSES_REGISTER_ALLOCATION_PASS_H_

View File

@ -7,6 +7,10 @@
'context_promotion_pass.h',
'dead_code_elimination_pass.cc',
'dead_code_elimination_pass.h',
'finalization_pass.cc',
'finalization_pass.h',
'register_allocation_pass.cc',
'register_allocation_pass.h',
#'dead_store_elimination_pass.cc',
#'dead_store_elimination_pass.h',
'simplification_pass.cc',

View File

@ -30,11 +30,16 @@ using namespace alloy::runtime;
PPCTranslator::PPCTranslator(PPCFrontend* frontend) :
frontend_(frontend) {
Backend* backend = frontend->runtime()->backend();
scanner_ = new PPCScanner(frontend);
builder_ = new PPCHIRBuilder(frontend);
compiler_ = new Compiler(frontend->runtime());
assembler_ = backend->CreateAssembler();
assembler_->Initialize();
// Passes are executed in the order they are added. Multiple of the same
// pass type may be used.
compiler_->AddPass(new passes::ContextPromotionPass());
compiler_->AddPass(new passes::SimplificationPass());
// TODO(benvanik): run repeatedly?
@ -45,9 +50,11 @@ PPCTranslator::PPCTranslator(PPCFrontend* frontend) :
//compiler_->AddPass(new passes::DeadStoreEliminationPass());
compiler_->AddPass(new passes::DeadCodeEliminationPass());
Backend* backend = frontend->runtime()->backend();
assembler_ = backend->CreateAssembler();
assembler_->Initialize();
// After register allocation instructions should not be added/removed.
compiler_->AddPass(new passes::RegisterAllocationPass(backend));
// Must come last. The HIR is not really HIR after this.
compiler_->AddPass(new passes::FinalizationPass());
}
PPCTranslator::~PPCTranslator() {

View File

@ -17,8 +17,6 @@ DebugInfo::DebugInfo() :
source_disasm_(0),
raw_hir_disasm_(0),
hir_disasm_(0),
raw_lir_disasm_(0),
lir_disasm_(0),
machine_code_disasm_(0) {
}
@ -26,7 +24,5 @@ DebugInfo::~DebugInfo() {
xe_free(source_disasm_);
xe_free(raw_hir_disasm_);
xe_free(hir_disasm_);
xe_free(raw_lir_disasm_);
xe_free(lir_disasm_);
xe_free(machine_code_disasm_);
}

View File

@ -23,9 +23,7 @@ enum DebugInfoFlags {
DEBUG_INFO_SOURCE_DISASM = (1 << 1),
DEBUG_INFO_RAW_HIR_DISASM = (1 << 2),
DEBUG_INFO_HIR_DISASM = (1 << 3),
DEBUG_INFO_RAW_LIR_DISASM = (1 << 4),
DEBUG_INFO_LIR_DISASM = (1 << 5),
DEBUG_INFO_MACHINE_CODE_DISASM = (1 << 6),
DEBUG_INFO_MACHINE_CODE_DISASM = (1 << 4),
DEBUG_INFO_ALL_DISASM = 0xFFFF,
};
@ -42,10 +40,6 @@ public:
void set_raw_hir_disasm(char* value) { raw_hir_disasm_ = value; }
const char* hir_disasm() const { return hir_disasm_; }
void set_hir_disasm(char* value) { hir_disasm_ = value; }
const char* raw_lir_disasm() const { return raw_lir_disasm_; }
void set_raw_lir_disasm(char* value) { raw_lir_disasm_ = value; }
const char* lir_disasm() const { return lir_disasm_; }
void set_lir_disasm(char* value) { lir_disasm_ = value; }
const char* machine_code_disasm() const { return machine_code_disasm_; }
void set_machine_code_disasm(char* value) { machine_code_disasm_ = value; }
@ -58,8 +52,6 @@ private:
char* source_disasm_;
char* raw_hir_disasm_;
char* hir_disasm_;
char* raw_lir_disasm_;
char* lir_disasm_;
char* machine_code_disasm_;
};

View File

@ -91,10 +91,10 @@ int Runtime::Initialize(Frontend* frontend, Backend* backend) {
#endif // ALLOY_HAS_IVM_BACKEND
if (FLAGS_runtime_backend == "any") {
#if defined(ALLOY_HAS_X64_BACKEND) && ALLOY_HAS_X64_BACKEND
/*if (!backend) {
if (!backend) {
backend = new alloy::backend::x64::X64Backend(
this);
}*/
}
#endif // ALLOY_HAS_X64_BACKEND
#if defined(ALLOY_HAS_IVM_BACKEND) && ALLOY_HAS_IVM_BACKEND
if (!backend) {

View File

@ -704,10 +704,6 @@ json_t* Processor::DumpFunction(uint64_t address, bool& succeeded) {
json_object_set_new(disasm_json, "rawHir", disasm_str_json);
disasm_str_json = json_string(debug_info->hir_disasm());
json_object_set_new(disasm_json, "hir", disasm_str_json);
disasm_str_json = json_string(debug_info->raw_lir_disasm());
json_object_set_new(disasm_json, "rawLir", disasm_str_json);
disasm_str_json = json_string(debug_info->lir_disasm());
json_object_set_new(disasm_json, "lir", disasm_str_json);
disasm_str_json = json_string(debug_info->machine_code_disasm());
json_object_set_new(disasm_json, "machineCode", disasm_str_json);
json_object_set_new(fn_json, "disasm", disasm_json);