From d4b0bf73c124623be8dbbc5cf8b9d061d4c08411 Mon Sep 17 00:00:00 2001 From: Ben Vanik Date: Sun, 20 Jan 2013 09:48:39 -0800 Subject: [PATCH] Prepping flow for basic block building. --- include/xenia/cpu/codegen.h | 14 ++++- include/xenia/cpu/exec_module.h | 9 +++ src/cpu/codegen.cc | 45 +++++++++++--- src/cpu/exec_module.cc | 5 +- src/cpu/ppc/instr_context.cc | 107 ++++++++++++++++++++++++++++++++ src/cpu/ppc/instr_context.h | 82 ++++++++++++++++++++++++ src/cpu/ppc/instr_ctx.h | 59 ------------------ src/cpu/ppc/sources.gypi | 1 + 8 files changed, 249 insertions(+), 73 deletions(-) create mode 100644 src/cpu/ppc/instr_context.cc create mode 100644 src/cpu/ppc/instr_context.h delete mode 100644 src/cpu/ppc/instr_ctx.h diff --git a/include/xenia/cpu/codegen.h b/include/xenia/cpu/codegen.h index 7b4563d05..dfc80e728 100644 --- a/include/xenia/cpu/codegen.h +++ b/include/xenia/cpu/codegen.h @@ -19,6 +19,7 @@ namespace llvm { class LLVMContext; class Module; + class FunctionType; class Function; class DIBuilder; class MDNode; @@ -30,6 +31,14 @@ namespace cpu { namespace codegen { +class CodegenFunction { +public: + sdb::FunctionSymbol* symbol; + llvm::FunctionType* function_type; + llvm::Function* function; +}; + + class CodegenContext { public: CodegenContext( @@ -48,7 +57,8 @@ private: void AddPresentImport( const xe_xex2_import_library_t *library, 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); xe_memory_ref memory_; @@ -60,6 +70,8 @@ private: llvm::Module* gen_module_; llvm::DIBuilder* di_builder_; llvm::MDNode* cu_; + + std::map functions_; }; diff --git a/include/xenia/cpu/exec_module.h b/include/xenia/cpu/exec_module.h index 7691ce9b4..9884a2a97 100644 --- a/include/xenia/cpu/exec_module.h +++ b/include/xenia/cpu/exec_module.h @@ -24,6 +24,14 @@ namespace llvm { class ExecutionEngine; } +namespace xe { +namespace cpu { +namespace codegen { + class CodegenContext; +} +} +} + namespace xe { namespace cpu { @@ -52,6 +60,7 @@ private: shared_ptr sdb_; shared_ptr context_; shared_ptr gen_module_; + auto_ptr codegen_; }; diff --git a/src/cpu/codegen.cc b/src/cpu/codegen.cc index cfb335c10..837e7e6e4 100644 --- a/src/cpu/codegen.cc +++ b/src/cpu/codegen.cc @@ -24,6 +24,7 @@ #include #include +#include "cpu/ppc/instr_context.h" using namespace llvm; using namespace xe; @@ -80,16 +81,22 @@ int CodegenContext::GenerateModule() { // // 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 functions; if (!sdb_->GetAllFunctions(functions)) { for (std::vector::iterator it = functions.begin(); it != functions.end(); ++it) { // kernel functions will be handled by the add imports handlers. if ((*it)->type == FunctionSymbol::User) { - AddFunction(*it); + PrepareFunction(*it); } } } + for (std::map::iterator it = + functions_.begin(); it != functions_.end(); ++it) { + BuildFunction(it->second); + } di_builder_->finalize(); @@ -186,7 +193,7 @@ void CodegenContext::AddPresentImport( // TODO(benvanik): add import thunk code. } -void CodegenContext::AddFunction(FunctionSymbol* fn) { +void CodegenContext::PrepareFunction(FunctionSymbol* fn) { Module* m = gen_module_; LLVMContext& context = m->getContext(); @@ -215,14 +222,32 @@ void CodegenContext::AddFunction(FunctionSymbol* fn) { f->setCallingConv(CallingConv::C); f->setVisibility(GlobalValue::DefaultVisibility); - // TODO(benvanik): generate code! - BasicBlock* block = BasicBlock::Create(context, "entry", f); - 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); + CodegenFunction* cgf = new CodegenFunction(); + cgf->symbol = fn; + cgf->function_type = ft; + cgf->function = f; + functions_.insert(std::pair(fn, cgf)); +} - // 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); uint32_t* pc = (uint32_t*)(mem + fn->start_address); @@ -241,7 +266,7 @@ void CodegenContext::AddFunction(FunctionSymbol* fn) { // Run the optimizer on the function. // Doing this here keeps the size of the IR small and speeds up the later // passes. - OptimizeFunction(m, f); + OptimizeFunction(gen_module_, cgf->function); } void CodegenContext::OptimizeFunction(Module* m, Function* fn) { diff --git a/src/cpu/exec_module.cc b/src/cpu/exec_module.cc index dbdf440dc..0a893c404 100644 --- a/src/cpu/exec_module.cc +++ b/src/cpu/exec_module.cc @@ -69,7 +69,6 @@ int ExecModule::Prepare() { OwningPtr shared_module_buffer; auto_ptr shared_module; auto_ptr outs; - auto_ptr codegen; PassManager pm; PassManagerBuilder pmb; @@ -116,10 +115,10 @@ int ExecModule::Prepare() { &error_message); // Build the module from the source code. - codegen = auto_ptr(new CodegenContext( + codegen_ = auto_ptr(new CodegenContext( memory_, export_resolver_.get(), module_, sdb_.get(), context_.get(), gen_module_.get())); - XEEXPECTZERO(codegen->GenerateModule()); + XEEXPECTZERO(codegen_->GenerateModule()); // Write to cache. outs = auto_ptr(new raw_fd_ostream( diff --git a/src/cpu/ppc/instr_context.cc b/src/cpu/ppc/instr_context.cc new file mode 100644 index 000000000..2463e1b32 --- /dev/null +++ b/src/cpu/ppc/instr_context.cc @@ -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) { + // +} diff --git a/src/cpu/ppc/instr_context.h b/src/cpu/ppc/instr_context.h new file mode 100644 index 000000000..22cad786b --- /dev/null +++ b/src/cpu/ppc/instr_context.h @@ -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 + +#include + + +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_ diff --git a/src/cpu/ppc/instr_ctx.h b/src/cpu/ppc/instr_ctx.h deleted file mode 100644 index 846a15744..000000000 --- a/src/cpu/ppc/instr_ctx.h +++ /dev/null @@ -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 - - -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_ diff --git a/src/cpu/ppc/sources.gypi b/src/cpu/ppc/sources.gypi index 4acb10332..964d6ffb2 100644 --- a/src/cpu/ppc/sources.gypi +++ b/src/cpu/ppc/sources.gypi @@ -2,5 +2,6 @@ { 'sources': [ 'instr.cc', + 'instr_context.cc', ], }