[Mesa-dev] [PATCH 12/13] clover: Add function for building a clover::module for non-TGSI targets v6

Francisco Jerez currojerez at riseup.net
Tue May 29 08:07:00 PDT 2012


Tom Stellard <tstellar at gmail.com> writes:

> v2:
>   -Separate IR type and LLVM triple
>   -Do the OpenCL C->LLVM IR and linking steps for all PIPE_SHADER_IR
>    types.
>
> v3:
>   - Coding style fixes
>   - Removed compatibility code for LLVM < 3.1
>   - Split build_module_llvm() into three functions:
>     compile(), link(), and build_module_llvm()
>
> v4:
>   - Use struct pipe_compute_program
>
> v5:
>   - Don't malloc memory for struct pipe_llvm_program
>
> v6:
>   - Fix serialization of llvm bytecode
> ---
>  .../state_trackers/clover/core/compiler.hpp        |    2 +
>  src/gallium/state_trackers/clover/core/program.cpp |    5 +-
>  .../state_trackers/clover/llvm/invocation.cpp      |  165 ++++++++++++++++++--
>  3 files changed, 158 insertions(+), 14 deletions(-)
>
> diff --git a/src/gallium/state_trackers/clover/core/compiler.hpp b/src/gallium/state_trackers/clover/core/compiler.hpp
> index 686c7d8..a43050a 100644
> --- a/src/gallium/state_trackers/clover/core/compiler.hpp
> +++ b/src/gallium/state_trackers/clover/core/compiler.hpp
> @@ -25,6 +25,7 @@
>  
>  #include "core/compat.hpp"
>  #include "core/module.hpp"
> +#include "pipe/p_defines.h"
>  
>  namespace clover {
>     class build_error {
> @@ -44,6 +45,7 @@ namespace clover {
>     };
>  
>     module compile_program_llvm(const compat::string &source,
> +                               enum pipe_shader_ir ir,
>                                 const compat::string &target);
>  
>     module compile_program_tgsi(const compat::string &source);
> diff --git a/src/gallium/state_trackers/clover/core/program.cpp b/src/gallium/state_trackers/clover/core/program.cpp
> index 06ac2af..6ca8080 100644
> --- a/src/gallium/state_trackers/clover/core/program.cpp
> +++ b/src/gallium/state_trackers/clover/core/program.cpp
> @@ -47,9 +47,10 @@ _cl_program::build(const std::vector<clover::device *> &devs) {
>  
>     for (auto dev : devs) {
>        try {
> -         auto module = (dev->ir_target() == "tgsi" ?
> +         auto module = (dev->ir_format() == PIPE_SHADER_IR_TGSI ?
>                          compile_program_tgsi(__source) :
> -                        compile_program_llvm(__source, dev->ir_target()));
> +                        compile_program_llvm(__source, dev->ir_format(),
> +			                     dev->ir_target()));
>           __binaries.insert({ dev, module });
>  
>        } catch (build_error &e) {
> diff --git a/src/gallium/state_trackers/clover/llvm/invocation.cpp b/src/gallium/state_trackers/clover/llvm/invocation.cpp
> index 89e21bf..27276bc 100644
> --- a/src/gallium/state_trackers/clover/llvm/invocation.cpp
> +++ b/src/gallium/state_trackers/clover/llvm/invocation.cpp
> @@ -22,24 +22,34 @@
>  
>  #include "core/compiler.hpp"
>  
> -#if 0
>  #include <clang/Frontend/CompilerInstance.h>
>  #include <clang/Frontend/TextDiagnosticPrinter.h>
>  #include <clang/CodeGen/CodeGenAction.h>
> +#include <llvm/Bitcode/BitstreamWriter.h>
> +#include <llvm/Bitcode/ReaderWriter.h>
> +#include <llvm/DerivedTypes.h>
> +#include <llvm/Linker.h>
>  #include <llvm/LLVMContext.h>
> +#include <llvm/Module.h>
> +#include <llvm/PassManager.h>
>  #include <llvm/Support/TargetSelect.h>
>  #include <llvm/Support/MemoryBuffer.h>
> +#include <llvm/Support/PathV1.h>
> +#include <llvm/Target/TargetData.h>
> +#include <llvm/Transforms/IPO/PassManagerBuilder.h>
> +
> +#include "pipe/p_state.h"
> +#include "util/u_memory.h"
>  
>  #include <iostream>
>  #include <iomanip>
>  #include <fstream>
>  #include <cstdio>
> -#endif
>  
>  using namespace clover;
>  
> -#if 0
>  namespace {
> +#if 0
>     void
>     build_binary(const std::string &source, const std::string &target,
>                  const std::string &name) {
> @@ -78,17 +88,148 @@ namespace {
>        compat::istream cs(str);
>        return module::deserialize(cs);
>     }
> -}
>  #endif
>  
> +   llvm::Module *
> +   compile(const std::string &source, const std::string &name,
> +           const std::string &triple) {
> +
> +      clang::CompilerInstance c;
> +      clang::EmitLLVMOnlyAction act(&llvm::getGlobalContext());
> +      std::string log;
> +      llvm::raw_string_ostream s_log(log);
> +
> +      c.getFrontendOpts().Inputs.push_back(
> +            clang::FrontendInputFile(name, clang::IK_OpenCL));
> +      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_PATH "/generic/include/",
> +                                      clang::frontend::Angled,
> +                                      false, 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.getInvocation().setLangDefaults(clang::IK_OpenCL);
> +      c.createDiagnostics(0, NULL, new clang::TextDiagnosticPrinter(
> +                          s_log, c.getDiagnosticOpts()));
> +
> +      c.getPreprocessorOpts().addRemappedFile(name,
> +                                      llvm::MemoryBuffer::getMemBuffer(source));
> +
> +      // Compile the code
> +      if (!c.ExecuteAction(act))
> +         throw build_error(log);
> +
> +      return act.takeModule();
> +   }
> +
> +   void
> +   link(llvm::Module *mod, const std::string &triple) {
> +
> +      llvm::PassManager PM;
> +      llvm::PassManagerBuilder Builder;
> +      bool isNative;
> +      llvm::Linker linker("clover", mod);
> +
> +      // Link the kernel with libclc
> +      linker.LinkInFile(llvm::sys::Path(LIBCLC_PATH + triple + "/lib/builtins.bc"), isNative);
> +      mod = linker.releaseModule();
> +
> +      // Run link time optimizations
> +      Builder.populateLTOPassManager(PM, false, true);
> +      Builder.OptLevel = 2;
> +      PM.run(*mod);
> +   }
> +
> +   module
> +   build_module_llvm(llvm::Module *mod) {
> +
> +      module m;
> +      struct pipe_llvm_program_header header;
> +
> +      llvm::SmallVector<char, 1024> llvm_bitcode;
> +      llvm::raw_svector_ostream bitcode_ostream(llvm_bitcode);
> +      llvm::BitstreamWriter writer(llvm_bitcode);
> +      llvm::WriteBitcodeToFile(mod, bitcode_ostream);
> +      bitcode_ostream.flush();
> +
> +      std::string kernel_name;
> +      compat::vector<module::argument> args;
> +      const llvm::NamedMDNode *kernel_node =
> +                                 mod->getNamedMetadata("opencl.kernels");
> +      // XXX: Support more than one kernel
> +      assert(kernel_node->getNumOperands() <= 1);
> +
> +      llvm::Function *kernel_func = llvm::dyn_cast<llvm::Function>(
> +                                   kernel_node->getOperand(0)->getOperand(0));
> +      kernel_name = kernel_func->getName();
> +
> +      for (llvm::Function::arg_iterator I = kernel_func->arg_begin(),
> +                                   E = kernel_func->arg_end(); I != E; ++I) {
> +         llvm::Argument &arg = *I;
> +         llvm::Type *arg_type = arg.getType();
> +         llvm::TargetData TD(kernel_func->getParent());
> +         unsigned arg_size = TD.getTypeStoreSize(arg_type);
> +
> +         if (llvm::isa<llvm::PointerType>(arg_type) && arg.hasByValAttr()) {
> +            arg_type =
> +               llvm::dyn_cast<llvm::PointerType>(arg_type)->getElementType();
> +         }
> +
> +         if (arg_type->isPointerTy()) {
> +            // XXX: Figure out LLVM->OpenCL address space mappings for each
> +            // target.  I think we need to ask clang what these are.  For now,
> +            // pretend everything is in the global address space.
> +            unsigned address_space = llvm::cast<llvm::PointerType>(arg_type)->getAddressSpace();
> +            switch (address_space) {
> +               default:
> +                  args.push_back(module::argument(module::argument::global, arg_size));
> +                  break;
> +            }
> +         } else {
> +            args.push_back(module::argument(module::argument::scalar, arg_size));
> +         }
> +      }
> +
> +      header.num_bytes = llvm_bitcode.size();
> +      std::string data;
> +      data.insert(0, (char*)(&header), sizeof(header));
> +      data.insert(data.end(), llvm_bitcode.begin(),
> +                                  llvm_bitcode.end());
> +      m.syms.push_back(module::symbol(kernel_name, 0, 0, args ));
> +      m.secs.push_back(module::section(0, module::section::text,
> +                                       header.num_bytes, data));
> +
> +      return m;
> +   }
> +} // End anonymous namespace
> +
>  module
>  clover::compile_program_llvm(const compat::string &source,
> -                             const compat::string &target) {
> -#if 0
> -   build_binary(source, target, "cl_input");
> -   module m = load_binary("cl_input.o");
> -   std::remove("cl_input.o");
> -   return m;
> -#endif
> -   return module();
> +                             enum pipe_shader_ir ir,
> +                             const compat::string &triple) {
> +
> +   llvm::Module *mod = compile(source, "cl_input", triple);
> +
> +   link(mod, triple);
> +
> +   // Build the clover::module
> +   switch (ir) {
> +      case PIPE_SHADER_IR_TGSI:
> +         //XXX: Handle TGSI
> +         assert(0);
> +         return module();
> +      default:
> +         return build_module_llvm(mod);
> +   }
>  }

Reviewed-by: Francisco Jerez <currojerez at riseup.net>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 229 bytes
Desc: not available
URL: <http://lists.freedesktop.org/archives/mesa-dev/attachments/20120529/df4ce459/attachment.pgp>


More information about the mesa-dev mailing list