Prepping flow for basic block building.

This commit is contained in:
Ben Vanik 2013-01-20 09:48:39 -08:00
parent ca2908db32
commit d4b0bf73c1
8 changed files with 249 additions and 73 deletions

View File

@ -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<sdb::FunctionSymbol*, CodegenFunction*> functions_;
};

View File

@ -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::SymbolDatabase> sdb_;
shared_ptr<llvm::LLVMContext> context_;
shared_ptr<llvm::Module> gen_module_;
auto_ptr<codegen::CodegenContext> codegen_;
};

View File

@ -24,6 +24,7 @@
#include <llvm/Transforms/IPO/PassManagerBuilder.h>
#include <xenia/cpu/ppc.h>
#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<FunctionSymbol*> functions;
if (!sdb_->GetAllFunctions(functions)) {
for (std::vector<FunctionSymbol*>::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<FunctionSymbol*, CodegenFunction*>::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<FunctionSymbol*, CodegenFunction*>(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) {

View File

@ -69,7 +69,6 @@ int ExecModule::Prepare() {
OwningPtr<MemoryBuffer> shared_module_buffer;
auto_ptr<Module> shared_module;
auto_ptr<raw_ostream> outs;
auto_ptr<CodegenContext> codegen;
PassManager pm;
PassManagerBuilder pmb;
@ -116,10 +115,10 @@ int ExecModule::Prepare() {
&error_message);
// 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(),
context_.get(), gen_module_.get()));
XEEXPECTZERO(codegen->GenerateModule());
XEEXPECTZERO(codegen_->GenerateModule());
// Write to cache.
outs = auto_ptr<raw_ostream>(new raw_fd_ostream(

View File

@ -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) {
//
}

View File

@ -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_

View File

@ -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_

View File

@ -2,5 +2,6 @@
{
'sources': [
'instr.cc',
'instr_context.cc',
],
}