Prepping flow for basic block building.
This commit is contained in:
parent
ca2908db32
commit
d4b0bf73c1
|
@ -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_;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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_;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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': [
|
||||
'instr.cc',
|
||||
'instr_context.cc',
|
||||
],
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue