--- .../state_trackers/clover/llvm/invocation.cpp | 234 ++------------------- 1 file changed, 23 insertions(+), 211 deletions(-)
diff --git a/src/gallium/state_trackers/clover/llvm/invocation.cpp b/src/gallium/state_trackers/clover/llvm/invocation.cpp index 4d11c24..d3347de 100644 --- a/src/gallium/state_trackers/clover/llvm/invocation.cpp +++ b/src/gallium/state_trackers/clover/llvm/invocation.cpp @@ -21,6 +21,7 @@ // #include "core/compiler.hpp" +#include "llvm/ir_compiler.hpp" #include <clang/Frontend/CompilerInstance.h> #include <clang/Frontend/TextDiagnosticBuffer.h> @@ -130,149 +131,6 @@ namespace { } } - llvm::Module * - compile_llvm(llvm::LLVMContext &llvm_ctx, const std::string &source, - const header_map &headers, - const std::string &name, const std::string &triple, - const std::string &processor, const std::string &opts, - clang::LangAS::Map& address_spaces, unsigned &optimization_level, - std::string &r_log) { - - clang::CompilerInstance c; - clang::EmitLLVMOnlyAction act(&llvm_ctx); - std::string log; - llvm::raw_string_ostream s_log(log); - std::string libclc_path = LIBCLC_LIBEXECDIR + processor + "-" - + triple + ".bc"; - - // Parse the compiler options: - std::vector<std::string> opts_array; - std::istringstream ss(opts); - - while (!ss.eof()) { - std::string opt; - getline(ss, opt, ' '); - opts_array.push_back(opt); - } - - opts_array.push_back(name); - - std::vector<const char *> opts_carray; - for (unsigned i = 0; i < opts_array.size(); i++) { - opts_carray.push_back(opts_array.at(i).c_str()); - } - - llvm::IntrusiveRefCntPtr<clang::DiagnosticIDs> DiagID; - llvm::IntrusiveRefCntPtr<clang::DiagnosticOptions> DiagOpts; - clang::TextDiagnosticBuffer *DiagsBuffer; - - DiagID = new clang::DiagnosticIDs(); - DiagOpts = new clang::DiagnosticOptions(); - DiagsBuffer = new clang::TextDiagnosticBuffer(); - - clang::DiagnosticsEngine Diags(DiagID, &*DiagOpts, DiagsBuffer); - bool Success; - - Success = clang::CompilerInvocation::CreateFromArgs(c.getInvocation(), - opts_carray.data(), - opts_carray.data() + opts_carray.size(), - Diags); - if (!Success) { - throw error(CL_INVALID_COMPILER_OPTIONS); - } - c.getFrontendOpts().ProgramAction = clang::frontend::EmitLLVMOnly; - c.getHeaderSearchOpts().UseBuiltinIncludes = true; - c.getHeaderSearchOpts().UseStandardSystemIncludes = true; - c.getHeaderSearchOpts().ResourceDir = CLANG_RESOURCE_DIR; - - // Add libclc generic search path - c.getHeaderSearchOpts().AddPath(LIBCLC_INCLUDEDIR, - clang::frontend::Angled, - false, false - ); - - // Add libclc include - c.getPreprocessorOpts().Includes.push_back("clc/clc.h"); - - // clc.h requires that this macro be defined: - c.getPreprocessorOpts().addMacroDef("cl_clang_storage_class_specifiers"); - - c.getLangOpts().NoBuiltin = true; - c.getTargetOpts().Triple = triple; - c.getTargetOpts().CPU = processor; - - // This is a workaround for a Clang bug which causes the number - // of warnings and errors to be printed to stderr. - // http://www.llvm.org/bugs/show_bug.cgi?id=19735 - c.getDiagnosticOpts().ShowCarets = false; - c.getInvocation().setLangDefaults(c.getLangOpts(), clang::IK_OpenCL, - clang::LangStandard::lang_opencl11); - c.createDiagnostics( - new clang::TextDiagnosticPrinter( - s_log, - &c.getDiagnosticOpts())); - -#if HAVE_LLVM >= 0x0306 - c.getPreprocessorOpts().addRemappedFile(name, - llvm::MemoryBuffer::getMemBuffer(source).release()); -#else - c.getPreprocessorOpts().addRemappedFile(name, - llvm::MemoryBuffer::getMemBuffer(source)); -#endif - - if (headers.size()) { - const std::string tmp_header_path = "/tmp/clover/"; - - c.getHeaderSearchOpts().AddPath(tmp_header_path, - clang::frontend::Angled, - false, false - ); - - for (header_map::const_iterator it = headers.begin(); - it != headers.end(); ++it) { - const std::string path = tmp_header_path + std::string(it->first); - c.getPreprocessorOpts().addRemappedFile(path, -#if HAVE_LLVM >= 0x0306 - llvm::MemoryBuffer::getMemBuffer(it->second.c_str()).release()); -#else - llvm::MemoryBuffer::getMemBuffer(it->second.c_str())); -#endif - } - } - - // Setting this attribute tells clang to link this file before - // performing any optimizations. This is required so that - // we can replace calls to the OpenCL C barrier() builtin - // with calls to target intrinsics that have the noduplicate - // attribute. This attribute will prevent Clang from creating - // illegal uses of barrier() (e.g. Moving barrier() inside a conditional - // that is no executed by all threads) during its optimizaton passes. -#if HAVE_LLVM >= 0x0308 - c.getCodeGenOpts().LinkBitcodeFiles.emplace_back(llvm::Linker::Flags::None, - libclc_path); -#else - c.getCodeGenOpts().LinkBitcodeFile = libclc_path; -#endif - optimization_level = c.getCodeGenOpts().OptimizationLevel; - - // Compile the code - bool ExecSuccess = c.ExecuteAction(act); - r_log = log; - - if (!ExecSuccess) - throw compile_error(); - - // Get address spaces map to be able to find kernel argument address space - memcpy(address_spaces, c.getTarget().getAddressSpaceMap(), - sizeof(address_spaces)); - -#if HAVE_LLVM >= 0x0306 - return act.takeModule().release(); -#else - return act.takeModule(); -#endif - } - std::vector<llvm::Function *> find_kernels(const llvm::Module *mod) { const llvm::NamedMDNode *kernel_node = @@ -297,57 +155,6 @@ namespace { return kernels; } - void - optimize(llvm::Module *mod, unsigned optimization_level) { - -#if HAVE_LLVM >= 0x0307 - llvm::legacy::PassManager PM; -#else - llvm::PassManager PM; -#endif - - const std::vector<llvm::Function *> kernels = find_kernels(mod); - - // Add a function internalizer pass. - // - // By default, the function internalizer pass will look for a function - // called "main" and then mark all other functions as internal. Marking - // functions as internal enables the optimizer to perform optimizations - // like function inlining and global dead-code elimination. - // - // When there is no "main" function in a module, the internalize pass will - // treat the module like a library, and it won't internalize any functions. - // Since there is no "main" function in our kernels, we need to tell - // the internalizer pass that this module is not a library by passing a - // list of kernel functions to the internalizer. The internalizer will - // treat the functions in the list as "main" functions and internalize - // all of the other functions. - std::vector<const char*> export_list; - for (std::vector<llvm::Function *>::const_iterator I = kernels.begin(), - E = kernels.end(); - I != E; ++I) { - llvm::Function *kernel = *I; - export_list.push_back(kernel->getName().data()); - } -#if HAVE_LLVM < 0x0306 - PM.add(new llvm::DataLayoutPass(mod)); -#elif HAVE_LLVM < 0x0307 - PM.add(new llvm::DataLayoutPass()); -#endif - PM.add(llvm::createInternalizePass(export_list)); - - llvm::PassManagerBuilder PMB; - PMB.OptLevel = optimization_level; -#if HAVE_LLVM < 0x0307 - PMB.LibraryInfo = new llvm::TargetLibraryInfo( -#else - PMB.LibraryInfo = new llvm::TargetLibraryInfoImpl( -#endif - llvm::Triple(mod->getTargetTriple())); - PMB.populateModulePassManager(PM); - PM.run(*mod); - } - // Kernel metadata struct kernel_arg_md { @@ -844,26 +651,28 @@ clover::compile_program_llvm(const std::string &source, init_targets(); - size_t processor_str_len = std::string(target).find_first_of("-"); - std::string processor(target, 0, processor_str_len); - std::string triple(target, processor_str_len + 1, - target.size() - processor_str_len - 1); - clang::LangAS::Map address_spaces; llvm::LLVMContext llvm_ctx; - unsigned optimization_level; llvm_ctx.setDiagnosticHandler(diagnostic_handler, &r_log); if (get_debug_flags() & DBG_CLC) debug_log("// Build options: " + opts + '\n' + source, ".cl"); - // The input file name must have the .cl extension in order for the - // CompilerInvocation class to recognize it as an OpenCL source file. - llvm::Module *mod = compile_llvm(llvm_ctx, source, headers, "input.cl", - triple, processor, opts, address_spaces, - optimization_level, r_log); + llvm_ir_compiler c(&llvm_ctx); + + try { + c.parse_args(target, opts); + c.compile(source, headers); + } catch (const error &) { + r_log = c.get_log(); + throw; + } + + c.optimize(); + + r_log = c.get_log(); - optimize(mod, optimization_level); + llvm::Module *mod = c.get_module(); if (get_debug_flags() & DBG_LLVM) { std::string log; @@ -873,6 +682,11 @@ clover::compile_program_llvm(const std::string &source, debug_log(log, ".ll"); } + const clang::TargetInfo &info = c.get_info(); + // Get address spaces map to be able to find kernel argument address space + clang::LangAS::Map address_spaces; + memcpy(address_spaces, info.getAddressSpaceMap(), sizeof(address_spaces)); + module m; // Build the clover::module switch (ir) { @@ -885,17 +699,15 @@ clover::compile_program_llvm(const std::string &source, m = build_module_llvm(mod, address_spaces); break; case PIPE_SHADER_IR_NATIVE: { - std::vector<char> code = compile_native(mod, triple, processor, + std::vector<char> code = compile_native(mod, + info.getTargetOpts().Triple, + info.getTargetOpts().CPU, get_debug_flags() & DBG_ASM, r_log); m = build_module_native(code, mod, address_spaces, r_log); break; } } -#if HAVE_LLVM >= 0x0306 - // LLVM 3.6 and newer, the user takes ownership of the module. - delete mod; -#endif return m; } -- 2.5.0 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev