diff --git a/include/xenia/cpu/codegen.h b/include/xenia/cpu/codegen.h index dfc80e728..f78f63683 100644 --- a/include/xenia/cpu/codegen.h +++ b/include/xenia/cpu/codegen.h @@ -50,13 +50,11 @@ public: int GenerateModule(); private: + CodegenFunction* GetCodegenFunction(uint32_t address); + void AddImports(); - void AddMissingImport( - const xe_xex2_import_library_t *library, - const xe_xex2_import_info_t* info, kernel::KernelExport* kernel_export); - void AddPresentImport( - const xe_xex2_import_library_t *library, - const xe_xex2_import_info_t* info, kernel::KernelExport* kernel_export); + void AddMissingImport(sdb::FunctionSymbol* fn); + void AddPresentImport(sdb::FunctionSymbol* fn); void PrepareFunction(sdb::FunctionSymbol* fn); void BuildFunction(CodegenFunction* cgf); void OptimizeFunction(llvm::Module* m, llvm::Function* fn); @@ -71,7 +69,7 @@ private: llvm::DIBuilder* di_builder_; llvm::MDNode* cu_; - std::map functions_; + std::map functions_; }; diff --git a/include/xenia/cpu/sdb.h b/include/xenia/cpu/sdb.h index b57bb56a2..6a76829b2 100644 --- a/include/xenia/cpu/sdb.h +++ b/include/xenia/cpu/sdb.h @@ -108,6 +108,7 @@ public: FunctionType type; uint32_t flags; + kernel::KernelExport* kernel_export; ExceptionEntrySymbol* ee; vector incoming_calls; diff --git a/src/cpu/codegen.cc b/src/cpu/codegen.cc index 837e7e6e4..9d272e367 100644 --- a/src/cpu/codegen.cc +++ b/src/cpu/codegen.cc @@ -74,9 +74,6 @@ int CodegenContext::GenerateModule() { 0); cu_ = (MDNode*)di_builder_->getCU(); - // Add import thunks/etc. - AddImports(); - // Add export wrappers. // @@ -87,13 +84,24 @@ int CodegenContext::GenerateModule() { 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) { - PrepareFunction(*it); + FunctionSymbol* fn = *it; + switch (fn->type) { + case FunctionSymbol::User: + PrepareFunction(fn); + break; + case FunctionSymbol::Kernel: + if (fn->kernel_export && fn->kernel_export->IsImplemented()) { + AddPresentImport(fn); + } else { + AddMissingImport(fn); + } + break; + default: + break; } } } - for (std::map::iterator it = + for (std::map::iterator it = functions_.begin(); it != functions_.end(); ++it) { BuildFunction(it->second); } @@ -103,90 +111,54 @@ int CodegenContext::GenerateModule() { return 0; } -void CodegenContext::AddImports() { - xe_xex2_ref xex = module_->xex(); - const xe_xex2_header_t* header = xe_xex2_get_header(xex); - - for (size_t n = 0; n < header->import_library_count; n++) { - const xe_xex2_import_library_t* library = &header->import_libraries[n]; - - xe_xex2_import_info_t* import_infos; - size_t import_info_count; - XEIGNORE(xe_xex2_get_import_infos(xex, library, - &import_infos, &import_info_count)); - - for (size_t i = 0; i < import_info_count; i++) { - const xe_xex2_import_info_t* info = &import_infos[i]; - KernelExport* kernel_export = export_resolver_->GetExportByOrdinal( - library->name, info->ordinal); - if (!kernel_export || !kernel_export->IsImplemented()) { - // Not implemented or known. - AddMissingImport(library, info, kernel_export); - } else { - // Implemented. - AddPresentImport(library, info, kernel_export); - } - } - - xe_free(import_infos); +CodegenFunction* CodegenContext::GetCodegenFunction(uint32_t address) { + std::map::iterator it = functions_.find(address); + if (it != functions_.end()) { + return it->second; } - - xe_xex2_release(xex); + return NULL; } -void CodegenContext::AddMissingImport( - const xe_xex2_import_library_t* library, - const xe_xex2_import_info_t* info, KernelExport* kernel_export) { +void CodegenContext::AddMissingImport(FunctionSymbol* fn) { Module* m = gen_module_; LLVMContext& context = m->getContext(); - char name[128]; - xesnprintfa(name, XECOUNT(name), "__thunk_%s_%.8X", - library->name, kernel_export->ordinal); + AttributeWithIndex awi[] = { + //AttributeWithIndex::get(context, 2, Attributes::NoCapture), + AttributeWithIndex::get(context, + AttributeSet::FunctionIndex, Attribute::NoUnwind), + }; + AttributeSet attrs = AttributeSet::get(context, awi); - // TODO(benvanik): add name as comment/alias? - // name = kernel_export->name; + std::vector args; + Type* return_type = Type::getInt32Ty(context); - if (info->thunk_address) { - AttributeWithIndex awi[] = { - //AttributeWithIndex::get(context, 2, Attributes::NoCapture), - AttributeWithIndex::get(context, - AttributeSet::FunctionIndex, Attribute::NoUnwind), - }; - AttributeSet attrs = AttributeSet::get(context, awi); + FunctionType* ft = FunctionType::get(return_type, + ArrayRef(args), false); + Function* f = cast(m->getOrInsertFunction( + StringRef(fn->name), ft, attrs)); + f->setCallingConv(CallingConv::C); + f->setVisibility(GlobalValue::DefaultVisibility); - std::vector args; - Type* return_type = Type::getInt32Ty(context); + // TODO(benvanik): log errors. + BasicBlock* block = BasicBlock::Create(context, "entry", f); + IRBuilder<> builder(block); + Value* tmp = builder.getInt32(0); + builder.CreateRet(tmp); - FunctionType* ft = FunctionType::get(return_type, - ArrayRef(args), false); - Function* f = cast(m->getOrInsertFunction( - StringRef(name), ft, attrs)); - f->setCallingConv(CallingConv::C); - f->setVisibility(GlobalValue::DefaultVisibility); + OptimizeFunction(m, f); - // TODO(benvanik): log errors. - BasicBlock* block = BasicBlock::Create(context, "entry", f); - IRBuilder<> builder(block); - Value* tmp = builder.getInt32(0); - builder.CreateRet(tmp); - - OptimizeFunction(m, f); - - //GlobalAlias *alias = new GlobalAlias(f->getType(), GlobalValue::InternalLinkage, name, f, m); - // printf(" F %.8X %.8X %.3X (%3d) %s %s\n", - // info->value_address, info->thunk_address, info->ordinal, - // info->ordinal, implemented ? " " : "!!", name); - } else { - // printf(" V %.8X %.3X (%3d) %s %s\n", - // info->value_address, info->ordinal, info->ordinal, - // implemented ? " " : "!!", name); - } + //GlobalAlias *alias = new GlobalAlias(f->getType(), GlobalValue::InternalLinkage, name, f, m); + // printf(" F %.8X %.8X %.3X (%3d) %s %s\n", + // info->value_address, info->thunk_address, info->ordinal, + // info->ordinal, implemented ? " " : "!!", name); + // For values: + // printf(" V %.8X %.3X (%3d) %s %s\n", + // info->value_address, info->ordinal, info->ordinal, + // implemented ? " " : "!!", name); } -void CodegenContext::AddPresentImport( - const xe_xex2_import_library_t* library, - const xe_xex2_import_info_t* info, KernelExport* kernel_export) { +void CodegenContext::AddPresentImport(FunctionSymbol* fn) { // Module *m = gen_module_; // LLVMContext& context = m->getContext(); @@ -212,7 +184,7 @@ void CodegenContext::PrepareFunction(FunctionSymbol* fn) { if (fn->name) { pname = fn->name; } else { - xesnprintfa(name, XECOUNT(name), "fn_%.8X", fn->start_address); + xesnprintfa(name, XECOUNT(name), "sub_%.8X", fn->start_address); } FunctionType* ft = FunctionType::get(return_type, @@ -226,43 +198,21 @@ void CodegenContext::PrepareFunction(FunctionSymbol* fn) { cgf->symbol = fn; cgf->function_type = ft; cgf->function = f; - functions_.insert(std::pair(fn, cgf)); + functions_.insert(std::pair( + fn->start_address, cgf)); } void CodegenContext::BuildFunction(CodegenFunction* cgf) { FunctionSymbol* fn = cgf->symbol; + printf("%s:\n", fn->name); + // Setup the generation context. - InstrContext ic(fn, context_, gen_module_, cgf->function); - // for each basic block: - // - ic.AddBasicBlock(bb); + InstrContext ic(memory_, fn, context_, gen_module_, cgf->function); // 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); - uint32_t pcdata = XEGETUINT32BE(pc); - printf("data %.8X %.8X\n", fn->start_address, pcdata); - InstrType* instr_type = ppc::GetInstrType(pcdata); - if (instr_type) { - printf("instr %.8X %s\n", fn->start_address, instr_type->name); - // xe_ppc_instr_t instr; - // instr.data.code = pcdata; - // printf("%d %d\n", instr.data.XFX.D, instr.data.XFX.spr); - } else { - printf("instr not found\n"); - } - // Run the optimizer on the function. // Doing this here keeps the size of the IR small and speeds up the later // passes. diff --git a/src/cpu/ppc/instr_context.cc b/src/cpu/ppc/instr_context.cc index 2463e1b32..96ce9f9b3 100644 --- a/src/cpu/ppc/instr_context.cc +++ b/src/cpu/ppc/instr_context.cc @@ -9,14 +9,23 @@ #include "cpu/ppc/instr_context.h" +#include +#include +#include +#include +#include +#include + 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) { +InstrContext::InstrContext(xe_memory_ref memory, FunctionSymbol* fn, + LLVMContext* context, Module* gen_module, + Function* gen_fn) { + memory_ = memory; fn_ = fn; context_ = context; gen_module_ = gen_module; @@ -42,15 +51,61 @@ llvm::Function* InstrContext::gen_fn() { return gen_fn_; } -void InstrContext::AddBasicBlock() { - // +void InstrContext::GenerateBasicBlocks() { + // Pass 1 creates all of the blocks - this way we can branch to them. + for (std::map::iterator it = fn_->blocks.begin(); + it != fn_->blocks.end(); ++it) { + FunctionBlock* block = it->second; + + char name[32]; + xesnprintfa(name, XECOUNT(name), "loc_%.8X", block->start_address); + BasicBlock* bb = BasicBlock::Create(*context_, name, gen_fn_); + bbs_.insert(std::pair(block->start_address, bb)); + } + + for (std::map::iterator it = fn_->blocks.begin(); + it != fn_->blocks.end(); ++it) { + FunctionBlock* block = it->second; + GenerateBasicBlock(block, GetBasicBlock(block->start_address)); + } } -void InstrContext::GenerateBasicBlocks() { - // +void InstrContext::GenerateBasicBlock(FunctionBlock* block, BasicBlock* bb) { + printf(" bb %.8X-%.8X:\n", block->start_address, block->end_address); + + //builder.SetCurrentDebugLocation(DebugLoc::get(fn->start_address >> 8, fn->start_address & 0xFF, ctx->cu)); + //i->setMetadata("some.name", MDNode::get(context, MDString::get(context, pname))); + + IRBuilder<> builder(bb); + + // Walk instructions in block. + uint8_t* p = xe_memory_addr(memory_, 0); + for (uint32_t ia = block->start_address; ia <= block->end_address; ia += 4) { + InstrData i; + i.address = ia; + i.code = XEGETUINT32BE(p + ia); + i.type = ppc::GetInstrType(i.code); + if (!i.type) { + XELOGCPU("Invalid instruction at %.8X: %.8X\n", ia, i.code); + continue; + } + printf(" %.8X: %.8X %s\n", ia, i.code, i.type->name); + // stash current bb? + // stash builder + //emit(this, i); + } + + Value* tmp = builder.getInt32(0); + builder.CreateRet(tmp); + + // TODO(benvanik): finish up BB } BasicBlock* InstrContext::GetBasicBlock(uint32_t address) { + std::map::iterator it = bbs_.find(address); + if (it != bbs_.end()) { + return it->second; + } return NULL; } diff --git a/src/cpu/ppc/instr_context.h b/src/cpu/ppc/instr_context.h index 22cad786b..ca04b271d 100644 --- a/src/cpu/ppc/instr_context.h +++ b/src/cpu/ppc/instr_context.h @@ -31,8 +31,9 @@ namespace ppc { class InstrContext { public: - InstrContext(sdb::FunctionSymbol* fn, llvm::LLVMContext* context, - llvm::Module* gen_module, llvm::Function* gen_fn); + InstrContext(xe_memory_ref memory, sdb::FunctionSymbol* fn, + llvm::LLVMContext* context, llvm::Module* gen_module, + llvm::Function* gen_fn); ~InstrContext(); sdb::FunctionSymbol* fn(); @@ -40,7 +41,6 @@ public: llvm::Module* gen_module(); llvm::Function* gen_fn(); - void AddBasicBlock(); void GenerateBasicBlocks(); llvm::BasicBlock* GetBasicBlock(uint32_t address); @@ -63,12 +63,17 @@ public: void write_memory(llvm::Value* addr, uint32_t size, llvm::Value* value); private: + void GenerateBasicBlock(sdb::FunctionBlock* block, llvm::BasicBlock* bb); + + xe_memory_ref memory_; sdb::FunctionSymbol* fn_; llvm::LLVMContext* context_; llvm::Module* gen_module_; llvm::Function* gen_fn_; // TODO(benvanik): IRBuilder/etc + std::map bbs_; + // Address of the instruction being generated. uint32_t cia_; }; diff --git a/src/cpu/sdb.cc b/src/cpu/sdb.cc index bbf21871c..161ca99b4 100644 --- a/src/cpu/sdb.cc +++ b/src/cpu/sdb.cc @@ -408,6 +408,7 @@ int SymbolDatabase::AddImports(const xe_xex2_import_library_t* library) { FunctionSymbol* fn = GetOrInsertFunction(info->thunk_address); fn->end_address = fn->start_address + 16 - 4; fn->type = FunctionSymbol::Kernel; + fn->kernel_export = kernel_export; if (kernel_export) { xesnprintfa(name, XECOUNT(name), "%s", kernel_export->name); } else { @@ -526,6 +527,7 @@ int SymbolDatabase::AnalyzeFunction(FunctionSymbol* fn) { } bool ends_block = false; + bool ends_fn = false; if (i.code == 0x4E800020) { // blr -- unconditional branch to LR. // This is generally a return. @@ -536,7 +538,7 @@ int SymbolDatabase::AnalyzeFunction(FunctionSymbol* fn) { } else { // Function end point. XELOGSDB("function end %.8X\n", addr); - break; + ends_fn = true; } ends_block = true; } else if (i.type->opcode == 0x48000000) { @@ -556,19 +558,22 @@ int SymbolDatabase::AnalyzeFunction(FunctionSymbol* fn) { if (target >= fn->start_address && target < addr && furthest_target <= addr) { XELOGSDB("function end %.8X (back b)\n", addr); - break; + ends_fn = true; } // If the target is a __restgprlr_* method it's the end of a function. // Note that sometimes functions stick this in a basic block *inside* // of the function somewhere, so ensure we don't have any branches over // it. - if (furthest_target <= addr && IsRestGprLr(target)) { + if (!ends_fn && + furthest_target <= addr && IsRestGprLr(target)) { XELOGSDB("function end %.8X (__restgprlr_*)\n", addr); - break; + ends_fn = true; } - furthest_target = MAX(furthest_target, target); + if (!ends_fn) { + furthest_target = MAX(furthest_target, target); + } } ends_block = true; } else if (i.type->opcode == 0x40000000) { @@ -609,6 +614,10 @@ int SymbolDatabase::AnalyzeFunction(FunctionSymbol* fn) { block = NULL; } + if (ends_fn) { + break; + } + addr += 4; if (fn->end_address && addr > fn->end_address) { // Hmm....