PPU LLVM: new mptr/cptr format

This commit is contained in:
Nekotekina 2017-06-29 17:25:39 +03:00
parent 85f8a42bd2
commit 3c064439b3
5 changed files with 34 additions and 6 deletions

View File

@ -375,6 +375,7 @@ jit_compiler::jit_compiler(const std::unordered_map<std::string, std::uintptr_t>
if (m_link.empty()) if (m_link.empty())
{ {
// Auxiliary JIT (does not use custom memory manager, only writes the objects)
m_engine.reset(llvm::EngineBuilder(std::make_unique<llvm::Module>("null_", m_context)) m_engine.reset(llvm::EngineBuilder(std::make_unique<llvm::Module>("null_", m_context))
.setErrorStr(&result) .setErrorStr(&result)
.setOptLevel(llvm::CodeGenOpt::Aggressive) .setOptLevel(llvm::CodeGenOpt::Aggressive)
@ -384,6 +385,7 @@ jit_compiler::jit_compiler(const std::unordered_map<std::string, std::uintptr_t>
} }
else else
{ {
// Primary JIT
auto mem = std::make_unique<MemoryManager>(m_link); auto mem = std::make_unique<MemoryManager>(m_link);
m_jit_el = std::make_unique<EventListener>(*mem); m_jit_el = std::make_unique<EventListener>(*mem);
@ -433,9 +435,9 @@ void jit_compiler::fin()
m_engine->finalizeObject(); m_engine->finalizeObject();
} }
u64 jit_compiler::get(const std::string & name) u64 jit_compiler::get(const std::string& name)
{ {
return m_engine->getFunctionAddress(name); return m_engine->getGlobalValueAddress(name);
} }
std::unordered_map<std::string, u64> jit_compiler::add(std::unordered_map<std::string, std::string> data) std::unordered_map<std::string, u64> jit_compiler::add(std::unordered_map<std::string, std::string> data)

View File

@ -66,6 +66,12 @@ public:
{ {
return m_cpu; return m_cpu;
} }
// Check JIT purpose
bool is_primary() const
{
return !m_link.empty();
}
}; };
#endif #endif

View File

@ -982,6 +982,9 @@ extern void ppu_initialize(const ppu_module& info)
// Worker threads // Worker threads
std::vector<std::thread> jthreads; std::vector<std::thread> jthreads;
// Global variables (pointers) to initialize
std::vector<std::pair<std::string, void*>> globals;
// Split module into fragments <= 1 MiB // Split module into fragments <= 1 MiB
std::size_t fpos = 0; std::size_t fpos = 0;
@ -1078,6 +1081,9 @@ extern void ppu_initialize(const ppu_module& info)
break; break;
} }
globals.emplace_back(fmt::format("__mptr%x", part.funcs[0].addr), vm::g_base_addr);
globals.emplace_back(fmt::format("__cptr%x", part.funcs[0].addr), vm::g_exec_addr);
// Check object file // Check object file
if (fs::is_file(Emu.GetCachePath() + obj_name)) if (fs::is_file(Emu.GetCachePath() + obj_name))
{ {
@ -1143,6 +1149,15 @@ extern void ppu_initialize(const ppu_module& info)
} }
} }
} }
// Initialize global variables
for (auto& var : globals)
{
if (u64 addr = jit.get(var.first))
{
*reinterpret_cast<void**>(addr) = var.second;
}
}
#endif #endif
} }
@ -1277,6 +1292,7 @@ static void ppu_initialize2(jit_compiler& jit, const ppu_module& module_part, co
{ {
out.flush(); out.flush();
LOG_ERROR(PPU, "LLVM: Verification failed for %s:\n%s", obj_name, result); LOG_ERROR(PPU, "LLVM: Verification failed for %s:\n%s", obj_name, result);
Emu.CallAfter([]{ Emu.Stop(); });
return; return;
} }

View File

@ -19,7 +19,9 @@ PPUTranslator::PPUTranslator(LLVMContext& context, Module* module, const ppu_mod
, m_pure_attr(AttributeSet::get(m_context, AttributeSet::FunctionIndex, {Attribute::NoUnwind, Attribute::ReadNone})) , m_pure_attr(AttributeSet::get(m_context, AttributeSet::FunctionIndex, {Attribute::NoUnwind, Attribute::ReadNone}))
{ {
// Memory base // Memory base
m_base = new GlobalVariable(*module, ArrayType::get(GetType<char>(), 0x100000000)->getPointerTo(), true, GlobalValue::ExternalLinkage, 0, "__mptr"); m_base = new GlobalVariable(*module, ArrayType::get(GetType<char>(), 0x100000000)->getPointerTo(), true, GlobalValue::ExternalLinkage, 0, fmt::format("__mptr%x", info.funcs[0].addr));
m_base->setInitializer(ConstantPointerNull::get(cast<PointerType>(m_base->getType()->getPointerElementType())));
m_base->setExternallyInitialized(true);
// Thread context struct (TODO: safer member access) // Thread context struct (TODO: safer member access)
const u32 off0 = offset32(&ppu_thread::state); const u32 off0 = offset32(&ppu_thread::state);
@ -42,7 +44,9 @@ PPUTranslator::PPUTranslator(LLVMContext& context, Module* module, const ppu_mod
m_thread_type = StructType::create(m_context, thread_struct, "context_t"); m_thread_type = StructType::create(m_context, thread_struct, "context_t");
// Callable // Callable
m_call = new GlobalVariable(*module, ArrayType::get(GetType<u32>(), 0x40000000)->getPointerTo(), true, GlobalValue::ExternalLinkage, 0, "__cptr"); m_call = new GlobalVariable(*module, ArrayType::get(GetType<u32>(), 0x40000000)->getPointerTo(), true, GlobalValue::ExternalLinkage, 0, fmt::format("__cptr%x", info.funcs[0].addr));
m_call->setInitializer(ConstantPointerNull::get(cast<PointerType>(m_call->getType()->getPointerElementType())));
m_call->setExternallyInitialized(true);
const auto md_name = MDString::get(m_context, "branch_weights"); const auto md_name = MDString::get(m_context, "branch_weights");
const auto md_low = ValueAsMetadata::get(ConstantInt::get(GetType<u32>(), 1)); const auto md_low = ValueAsMetadata::get(ConstantInt::get(GetType<u32>(), 1));

View File

@ -134,14 +134,14 @@ class PPUTranslator final //: public CPUTranslator
/* Variables */ /* Variables */
// Memory base // Memory base
llvm::Value* m_base; llvm::GlobalVariable* m_base;
llvm::Value* m_base_loaded; llvm::Value* m_base_loaded;
// Thread context // Thread context
llvm::Value* m_thread; llvm::Value* m_thread;
// Callable functions // Callable functions
llvm::Value* m_call; llvm::GlobalVariable* m_call;
// Main block // Main block
llvm::BasicBlock* m_body; llvm::BasicBlock* m_body;