Prepping flow for basic block building.
This commit is contained in:
parent
ca2908db32
commit
d4b0bf73c1
|
@ -19,6 +19,7 @@
|
||||||
namespace llvm {
|
namespace llvm {
|
||||||
class LLVMContext;
|
class LLVMContext;
|
||||||
class Module;
|
class Module;
|
||||||
|
class FunctionType;
|
||||||
class Function;
|
class Function;
|
||||||
class DIBuilder;
|
class DIBuilder;
|
||||||
class MDNode;
|
class MDNode;
|
||||||
|
@ -30,6 +31,14 @@ namespace cpu {
|
||||||
namespace codegen {
|
namespace codegen {
|
||||||
|
|
||||||
|
|
||||||
|
class CodegenFunction {
|
||||||
|
public:
|
||||||
|
sdb::FunctionSymbol* symbol;
|
||||||
|
llvm::FunctionType* function_type;
|
||||||
|
llvm::Function* function;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
class CodegenContext {
|
class CodegenContext {
|
||||||
public:
|
public:
|
||||||
CodegenContext(
|
CodegenContext(
|
||||||
|
@ -48,7 +57,8 @@ private:
|
||||||
void AddPresentImport(
|
void AddPresentImport(
|
||||||
const xe_xex2_import_library_t *library,
|
const xe_xex2_import_library_t *library,
|
||||||
const xe_xex2_import_info_t* info, kernel::KernelExport* kernel_export);
|
const xe_xex2_import_info_t* info, kernel::KernelExport* kernel_export);
|
||||||
void AddFunction(sdb::FunctionSymbol* fn);
|
void PrepareFunction(sdb::FunctionSymbol* fn);
|
||||||
|
void BuildFunction(CodegenFunction* cgf);
|
||||||
void OptimizeFunction(llvm::Module* m, llvm::Function* fn);
|
void OptimizeFunction(llvm::Module* m, llvm::Function* fn);
|
||||||
|
|
||||||
xe_memory_ref memory_;
|
xe_memory_ref memory_;
|
||||||
|
@ -60,6 +70,8 @@ private:
|
||||||
llvm::Module* gen_module_;
|
llvm::Module* gen_module_;
|
||||||
llvm::DIBuilder* di_builder_;
|
llvm::DIBuilder* di_builder_;
|
||||||
llvm::MDNode* cu_;
|
llvm::MDNode* cu_;
|
||||||
|
|
||||||
|
std::map<sdb::FunctionSymbol*, CodegenFunction*> functions_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,14 @@ namespace llvm {
|
||||||
class ExecutionEngine;
|
class ExecutionEngine;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace xe {
|
||||||
|
namespace cpu {
|
||||||
|
namespace codegen {
|
||||||
|
class CodegenContext;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
namespace xe {
|
namespace xe {
|
||||||
namespace cpu {
|
namespace cpu {
|
||||||
|
@ -52,6 +60,7 @@ private:
|
||||||
shared_ptr<sdb::SymbolDatabase> sdb_;
|
shared_ptr<sdb::SymbolDatabase> sdb_;
|
||||||
shared_ptr<llvm::LLVMContext> context_;
|
shared_ptr<llvm::LLVMContext> context_;
|
||||||
shared_ptr<llvm::Module> gen_module_;
|
shared_ptr<llvm::Module> gen_module_;
|
||||||
|
auto_ptr<codegen::CodegenContext> codegen_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include <llvm/Transforms/IPO/PassManagerBuilder.h>
|
#include <llvm/Transforms/IPO/PassManagerBuilder.h>
|
||||||
|
|
||||||
#include <xenia/cpu/ppc.h>
|
#include <xenia/cpu/ppc.h>
|
||||||
|
#include "cpu/ppc/instr_context.h"
|
||||||
|
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
using namespace xe;
|
using namespace xe;
|
||||||
|
@ -80,16 +81,22 @@ int CodegenContext::GenerateModule() {
|
||||||
//
|
//
|
||||||
|
|
||||||
// Add all functions.
|
// Add all functions.
|
||||||
|
// We do two passes - the first creates the function signature and global
|
||||||
|
// value (so that we can call it), the second actually builds the function.
|
||||||
std::vector<FunctionSymbol*> functions;
|
std::vector<FunctionSymbol*> functions;
|
||||||
if (!sdb_->GetAllFunctions(functions)) {
|
if (!sdb_->GetAllFunctions(functions)) {
|
||||||
for (std::vector<FunctionSymbol*>::iterator it = functions.begin();
|
for (std::vector<FunctionSymbol*>::iterator it = functions.begin();
|
||||||
it != functions.end(); ++it) {
|
it != functions.end(); ++it) {
|
||||||
// kernel functions will be handled by the add imports handlers.
|
// kernel functions will be handled by the add imports handlers.
|
||||||
if ((*it)->type == FunctionSymbol::User) {
|
if ((*it)->type == FunctionSymbol::User) {
|
||||||
AddFunction(*it);
|
PrepareFunction(*it);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for (std::map<FunctionSymbol*, CodegenFunction*>::iterator it =
|
||||||
|
functions_.begin(); it != functions_.end(); ++it) {
|
||||||
|
BuildFunction(it->second);
|
||||||
|
}
|
||||||
|
|
||||||
di_builder_->finalize();
|
di_builder_->finalize();
|
||||||
|
|
||||||
|
@ -186,7 +193,7 @@ void CodegenContext::AddPresentImport(
|
||||||
// TODO(benvanik): add import thunk code.
|
// TODO(benvanik): add import thunk code.
|
||||||
}
|
}
|
||||||
|
|
||||||
void CodegenContext::AddFunction(FunctionSymbol* fn) {
|
void CodegenContext::PrepareFunction(FunctionSymbol* fn) {
|
||||||
Module* m = gen_module_;
|
Module* m = gen_module_;
|
||||||
LLVMContext& context = m->getContext();
|
LLVMContext& context = m->getContext();
|
||||||
|
|
||||||
|
@ -215,14 +222,32 @@ void CodegenContext::AddFunction(FunctionSymbol* fn) {
|
||||||
f->setCallingConv(CallingConv::C);
|
f->setCallingConv(CallingConv::C);
|
||||||
f->setVisibility(GlobalValue::DefaultVisibility);
|
f->setVisibility(GlobalValue::DefaultVisibility);
|
||||||
|
|
||||||
// TODO(benvanik): generate code!
|
CodegenFunction* cgf = new CodegenFunction();
|
||||||
BasicBlock* block = BasicBlock::Create(context, "entry", f);
|
cgf->symbol = fn;
|
||||||
IRBuilder<> builder(block);
|
cgf->function_type = ft;
|
||||||
//builder.SetCurrentDebugLocation(DebugLoc::get(fn->start_address >> 8, fn->start_address & 0xFF, ctx->cu));
|
cgf->function = f;
|
||||||
Value* tmp = builder.getInt32(0);
|
functions_.insert(std::pair<FunctionSymbol*, CodegenFunction*>(fn, cgf));
|
||||||
builder.CreateRet(tmp);
|
}
|
||||||
|
|
||||||
// i->setMetadata("some.name", MDNode::get(context, MDString::get(context, pname)));
|
void CodegenContext::BuildFunction(CodegenFunction* cgf) {
|
||||||
|
FunctionSymbol* fn = cgf->symbol;
|
||||||
|
|
||||||
|
// Setup the generation context.
|
||||||
|
InstrContext ic(fn, context_, gen_module_, cgf->function);
|
||||||
|
// for each basic block:
|
||||||
|
// - ic.AddBasicBlock(bb);
|
||||||
|
|
||||||
|
// Run through and generate each basic block.
|
||||||
|
ic.GenerateBasicBlocks();
|
||||||
|
|
||||||
|
// // TODO(benvanik): generate code!
|
||||||
|
// BasicBlock* block = BasicBlock::Create(*context_, "entry", cgf->function);
|
||||||
|
// IRBuilder<> builder(block);
|
||||||
|
// //builder.SetCurrentDebugLocation(DebugLoc::get(fn->start_address >> 8, fn->start_address & 0xFF, ctx->cu));
|
||||||
|
// Value* tmp = builder.getInt32(0);
|
||||||
|
// builder.CreateRet(tmp);
|
||||||
|
|
||||||
|
// // i->setMetadata("some.name", MDNode::get(context, MDString::get(context, pname)));
|
||||||
|
|
||||||
uint8_t* mem = xe_memory_addr(memory_, 0);
|
uint8_t* mem = xe_memory_addr(memory_, 0);
|
||||||
uint32_t* pc = (uint32_t*)(mem + fn->start_address);
|
uint32_t* pc = (uint32_t*)(mem + fn->start_address);
|
||||||
|
@ -241,7 +266,7 @@ void CodegenContext::AddFunction(FunctionSymbol* fn) {
|
||||||
// Run the optimizer on the function.
|
// Run the optimizer on the function.
|
||||||
// Doing this here keeps the size of the IR small and speeds up the later
|
// Doing this here keeps the size of the IR small and speeds up the later
|
||||||
// passes.
|
// passes.
|
||||||
OptimizeFunction(m, f);
|
OptimizeFunction(gen_module_, cgf->function);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CodegenContext::OptimizeFunction(Module* m, Function* fn) {
|
void CodegenContext::OptimizeFunction(Module* m, Function* fn) {
|
||||||
|
|
|
@ -69,7 +69,6 @@ int ExecModule::Prepare() {
|
||||||
OwningPtr<MemoryBuffer> shared_module_buffer;
|
OwningPtr<MemoryBuffer> shared_module_buffer;
|
||||||
auto_ptr<Module> shared_module;
|
auto_ptr<Module> shared_module;
|
||||||
auto_ptr<raw_ostream> outs;
|
auto_ptr<raw_ostream> outs;
|
||||||
auto_ptr<CodegenContext> codegen;
|
|
||||||
|
|
||||||
PassManager pm;
|
PassManager pm;
|
||||||
PassManagerBuilder pmb;
|
PassManagerBuilder pmb;
|
||||||
|
@ -116,10 +115,10 @@ int ExecModule::Prepare() {
|
||||||
&error_message);
|
&error_message);
|
||||||
|
|
||||||
// Build the module from the source code.
|
// Build the module from the source code.
|
||||||
codegen = auto_ptr<CodegenContext>(new CodegenContext(
|
codegen_ = auto_ptr<CodegenContext>(new CodegenContext(
|
||||||
memory_, export_resolver_.get(), module_, sdb_.get(),
|
memory_, export_resolver_.get(), module_, sdb_.get(),
|
||||||
context_.get(), gen_module_.get()));
|
context_.get(), gen_module_.get()));
|
||||||
XEEXPECTZERO(codegen->GenerateModule());
|
XEEXPECTZERO(codegen_->GenerateModule());
|
||||||
|
|
||||||
// Write to cache.
|
// Write to cache.
|
||||||
outs = auto_ptr<raw_ostream>(new raw_fd_ostream(
|
outs = auto_ptr<raw_ostream>(new raw_fd_ostream(
|
||||||
|
|
|
@ -0,0 +1,107 @@
|
||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
* 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 "cpu/ppc/instr_context.h"
|
||||||
|
|
||||||
|
|
||||||
|
using namespace llvm;
|
||||||
|
using namespace xe::cpu::ppc;
|
||||||
|
using namespace xe::cpu::sdb;
|
||||||
|
|
||||||
|
|
||||||
|
InstrContext::InstrContext(FunctionSymbol* fn, LLVMContext* context,
|
||||||
|
Module* gen_module, Function* gen_fn) {
|
||||||
|
fn_ = fn;
|
||||||
|
context_ = context;
|
||||||
|
gen_module_ = gen_module;
|
||||||
|
gen_fn_ = gen_fn;
|
||||||
|
}
|
||||||
|
|
||||||
|
InstrContext::~InstrContext() {
|
||||||
|
}
|
||||||
|
|
||||||
|
FunctionSymbol* InstrContext::fn() {
|
||||||
|
return fn_;
|
||||||
|
}
|
||||||
|
|
||||||
|
llvm::LLVMContext* InstrContext::context() {
|
||||||
|
return context_;
|
||||||
|
}
|
||||||
|
|
||||||
|
llvm::Module* InstrContext::gen_module() {
|
||||||
|
return gen_module_;
|
||||||
|
}
|
||||||
|
|
||||||
|
llvm::Function* InstrContext::gen_fn() {
|
||||||
|
return gen_fn_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void InstrContext::AddBasicBlock() {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
void InstrContext::GenerateBasicBlocks() {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
BasicBlock* InstrContext::GetBasicBlock(uint32_t address) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
Function* InstrContext::GetFunction(uint32_t addr) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
Value* InstrContext::cia_value() {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
Value* InstrContext::nia_value() {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void InstrContext::update_nia_value(Value* value) {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
Value* InstrContext::spr_value(uint32_t n) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void InstrContext::update_spr_value(uint32_t n, Value* value) {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
Value* InstrContext::cr_value() {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void InstrContext::update_cr_value(Value* value) {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
Value* InstrContext::gpr_value(uint32_t n) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void InstrContext::update_gpr_value(uint32_t n, Value* value) {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
Value* InstrContext::memory_addr(uint32_t addr) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
Value* InstrContext::read_memory(Value* addr, uint32_t size, bool extend) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void InstrContext::write_memory(Value* addr, uint32_t size, Value* value) {
|
||||||
|
//
|
||||||
|
}
|
|
@ -0,0 +1,82 @@
|
||||||
|
/**
|
||||||
|
******************************************************************************
|
||||||
|
* 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 XENIA_CPU_PPC_INSTR_CONTEXT_H_
|
||||||
|
#define XENIA_CPU_PPC_INSTR_CONTEXT_H_
|
||||||
|
|
||||||
|
#include <xenia/cpu/ppc/instr.h>
|
||||||
|
|
||||||
|
#include <xenia/cpu/sdb.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace llvm {
|
||||||
|
class LLVMContext;
|
||||||
|
class Module;
|
||||||
|
class Function;
|
||||||
|
class BasicBlock;
|
||||||
|
class Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
namespace xe {
|
||||||
|
namespace cpu {
|
||||||
|
namespace ppc {
|
||||||
|
|
||||||
|
|
||||||
|
class InstrContext {
|
||||||
|
public:
|
||||||
|
InstrContext(sdb::FunctionSymbol* fn, llvm::LLVMContext* context,
|
||||||
|
llvm::Module* gen_module, llvm::Function* gen_fn);
|
||||||
|
~InstrContext();
|
||||||
|
|
||||||
|
sdb::FunctionSymbol* fn();
|
||||||
|
llvm::LLVMContext* context();
|
||||||
|
llvm::Module* gen_module();
|
||||||
|
llvm::Function* gen_fn();
|
||||||
|
|
||||||
|
void AddBasicBlock();
|
||||||
|
void GenerateBasicBlocks();
|
||||||
|
llvm::BasicBlock* GetBasicBlock(uint32_t address);
|
||||||
|
|
||||||
|
llvm::Function* GetFunction(uint32_t addr);
|
||||||
|
|
||||||
|
llvm::Value* cia_value();
|
||||||
|
llvm::Value* nia_value();
|
||||||
|
void update_nia_value(llvm::Value* value);
|
||||||
|
llvm::Value* spr_value(uint32_t n);
|
||||||
|
void update_spr_value(uint32_t n, llvm::Value* value);
|
||||||
|
|
||||||
|
llvm::Value* cr_value();
|
||||||
|
void update_cr_value(llvm::Value* value);
|
||||||
|
|
||||||
|
llvm::Value* gpr_value(uint32_t n);
|
||||||
|
void update_gpr_value(uint32_t n, llvm::Value* value);
|
||||||
|
|
||||||
|
llvm::Value* memory_addr(uint32_t addr);
|
||||||
|
llvm::Value* read_memory(llvm::Value* addr, uint32_t size, bool extend);
|
||||||
|
void write_memory(llvm::Value* addr, uint32_t size, llvm::Value* value);
|
||||||
|
|
||||||
|
private:
|
||||||
|
sdb::FunctionSymbol* fn_;
|
||||||
|
llvm::LLVMContext* context_;
|
||||||
|
llvm::Module* gen_module_;
|
||||||
|
llvm::Function* gen_fn_;
|
||||||
|
// TODO(benvanik): IRBuilder/etc
|
||||||
|
|
||||||
|
// Address of the instruction being generated.
|
||||||
|
uint32_t cia_;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace ppc
|
||||||
|
} // namespace cpu
|
||||||
|
} // namespace xe
|
||||||
|
|
||||||
|
|
||||||
|
#endif // XENIA_CPU_PPC_INSTR_CONTEXT_H_
|
|
@ -1,59 +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 XENIA_CPU_PPC_INSTR_CTX_H_
|
|
||||||
#define XENIA_CPU_PPC_INSTR_CTX_H_
|
|
||||||
|
|
||||||
#include <xenia/cpu/ppc/instr.h>
|
|
||||||
|
|
||||||
|
|
||||||
namespace xe {
|
|
||||||
namespace cpu {
|
|
||||||
namespace ppc {
|
|
||||||
|
|
||||||
|
|
||||||
class InstrContext {
|
|
||||||
using namespace llvm;
|
|
||||||
public:
|
|
||||||
InstrContext();
|
|
||||||
|
|
||||||
Value* cia();
|
|
||||||
Value* nia();
|
|
||||||
void set_nia(Value* value);
|
|
||||||
Value* spr(uint32_t n);
|
|
||||||
void set_spr(uint32_t n, Value* value);
|
|
||||||
|
|
||||||
Value* cr();
|
|
||||||
void set_cr(Value* value);
|
|
||||||
|
|
||||||
Value* gpr(uint32_t n);
|
|
||||||
void set_gpr(uint32_t n, Value* value);
|
|
||||||
|
|
||||||
Value* get_memory_addr(uint32_t addr);
|
|
||||||
Value* read_memory(Value* addr, uint32_t size, bool extend);
|
|
||||||
void write_memory(Value* addr, uint32_t size, Value* value);
|
|
||||||
|
|
||||||
LLVMContext& context;
|
|
||||||
Module& module;
|
|
||||||
// TODO(benvanik): IRBuilder/etc
|
|
||||||
|
|
||||||
// Address of the instruction being generated.
|
|
||||||
uint32_t cia;
|
|
||||||
|
|
||||||
private:
|
|
||||||
//
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace ppc
|
|
||||||
} // namespace cpu
|
|
||||||
} // namespace xe
|
|
||||||
|
|
||||||
|
|
||||||
#endif // XENIA_CPU_PPC_INSTR_CTX_H_
|
|
|
@ -2,5 +2,6 @@
|
||||||
{
|
{
|
||||||
'sources': [
|
'sources': [
|
||||||
'instr.cc',
|
'instr.cc',
|
||||||
|
'instr_context.cc',
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue