From 86f36b3081cd3d96f86d43c7cfda367cac7350ba Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Sun, 23 Oct 2016 17:43:18 +0200 Subject: [PATCH] Add function returning the generated assembly for a given llvm module --- src/r_compiler/llvmdrawers.cpp | 89 +++++++++++++++++++++++++++------- 1 file changed, 72 insertions(+), 17 deletions(-) diff --git a/src/r_compiler/llvmdrawers.cpp b/src/r_compiler/llvmdrawers.cpp index c936d62603..ba1fb4efcc 100644 --- a/src/r_compiler/llvmdrawers.cpp +++ b/src/r_compiler/llvmdrawers.cpp @@ -20,7 +20,9 @@ class LLVMProgram public: LLVMProgram(); + void CreateModule(); void CreateEE(); + std::string GenerateAssembly(std::string cpuName); std::string DumpModule(); void StopLogFatalErrors(); @@ -85,6 +87,8 @@ LLVMDrawers *LLVMDrawers::Instance() LLVMDrawersImpl::LLVMDrawersImpl() { + mProgram.CreateModule(); + CodegenDrawColumn("FillColumn", DrawColumnVariant::Fill, DrawColumnMethod::Normal); CodegenDrawColumn("FillColumnAdd", DrawColumnVariant::FillAdd, DrawColumnMethod::Normal); CodegenDrawColumn("FillColumnAddClamp", DrawColumnVariant::FillAddClamp, DrawColumnMethod::Normal); @@ -447,7 +451,11 @@ LLVMProgram::LLVMProgram() InitializeNativeTargetAsmPrinter(); mContext = std::make_unique(); - mModule = std::make_unique("render", context()); +} + +void LLVMProgram::CreateModule() +{ + mModule = std::make_unique("render", context()); } void LLVMProgram::CreateEE() @@ -456,22 +464,6 @@ void LLVMProgram::CreateEE() std::string errorstring; -#if 0 - std::string targetTriple = sys::getProcessTriple(); - StringMap cpuFeatures; - sys::getHostCPUFeatures(cpuFeatures); - std::string cpuFeaturesStr; - for (const auto &it : cpuFeatures) - { - if (!cpuFeaturesStr.empty()) - cpuFeaturesStr.push_back(' '); - cpuFeaturesStr.push_back(it.getValue() ? '+' : '-'); - cpuFeaturesStr += it.getKey(); - } - - Printf("LLVM CPU features: %s\n", cpuFeaturesStr.c_str()); -#endif - llvm::Module *module = mModule.get(); EngineBuilder engineBuilder(std::move(mModule)); engineBuilder.setErrorStr(&errorstring); @@ -532,6 +524,69 @@ void LLVMProgram::CreateEE() mEngine->finalizeObject(); } +std::string LLVMProgram::GenerateAssembly(std::string cpuName) +{ + using namespace llvm; + + std::string errorstring; + + llvm::Module *module = mModule.get(); + EngineBuilder engineBuilder(std::move(mModule)); + engineBuilder.setErrorStr(&errorstring); + engineBuilder.setOptLevel(CodeGenOpt::Aggressive); + engineBuilder.setEngineKind(EngineKind::JIT); + engineBuilder.setMCPU(cpuName); + machine = engineBuilder.selectTarget(); + if (!machine) + I_FatalError("Could not create LLVM target machine"); + + std::string targetTriple = machine->getTargetTriple().getTriple(); + + module->setTargetTriple(targetTriple); +#if LLVM_VERSION_MAJOR < 3 || (LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR < 8) + module->setDataLayout(new DataLayout(*machine->getSubtargetImpl()->getDataLayout())); +#else + module->setDataLayout(machine->createDataLayout()); +#endif + + legacy::FunctionPassManager PerFunctionPasses(module); + legacy::PassManager PerModulePasses; + +#if LLVM_VERSION_MAJOR > 3 || (LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR >= 8) + PerFunctionPasses.add(createTargetTransformInfoWrapperPass(machine->getTargetIRAnalysis())); + PerModulePasses.add(createTargetTransformInfoWrapperPass(machine->getTargetIRAnalysis())); +#endif + + SmallString<16*1024> str; + raw_svector_ostream stream(str); + machine->addPassesToEmitFile(PerModulePasses, stream, TargetMachine::CGFT_AssemblyFile); + PerModulePasses.add(createPrintMIRPass(stream)); + + PassManagerBuilder passManagerBuilder; + passManagerBuilder.OptLevel = 3; + passManagerBuilder.SizeLevel = 0; + passManagerBuilder.Inliner = createFunctionInliningPass(); + passManagerBuilder.SLPVectorize = true; + passManagerBuilder.LoopVectorize = true; + passManagerBuilder.LoadCombine = true; + passManagerBuilder.populateModulePassManager(PerModulePasses); + passManagerBuilder.populateFunctionPassManager(PerFunctionPasses); + + // Run function passes: + PerFunctionPasses.doInitialization(); + for (llvm::Function &func : *module) + { + if (!func.isDeclaration()) + PerFunctionPasses.run(func); + } + PerFunctionPasses.doFinalization(); + + // Run module passes: + PerModulePasses.run(*module); + + return str.c_str(); +} + std::string LLVMProgram::DumpModule() { std::string str;