tstel...@gmail.com writes: > From: Tom Stellard <thomas.stell...@amd.com> > > 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 > --- > .../state_trackers/clover/core/compiler.hpp | 2 + > src/gallium/state_trackers/clover/core/program.cpp | 9 +- > .../state_trackers/clover/llvm/invocation.cpp | 167 > ++++++++++++++++++-- > 3 files changed, 164 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..8e34696 100644 > --- a/src/gallium/state_trackers/clover/core/program.cpp > +++ b/src/gallium/state_trackers/clover/core/program.cpp > @@ -47,9 +47,14 @@ _cl_program::build(const std::vector<clover::device *> > &devs) { > > for (auto dev : devs) { > try { > - auto module = (dev->ir_target() == "tgsi" ? > + // XXX: We need to check the input source to determine which > + // compile_program() call to use. If the input is TGSI we > + // should use compile_program_tgsi, otherwise we should use > + // compile_program_llvm > + 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..92f132b 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,150 @@ 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_compute_program * program; > + > + 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(); > + > + program = (struct pipe_compute_program *) > + MALLOC(sizeof(struct pipe_compute_program)); > + > + program->num_bytes = llvm_bitcode.size() * sizeof(unsigned char); > + program->prog = (unsigned char *)MALLOC(program->num_bytes); > + memcpy(program->prog, &llvm_bitcode[0], program->num_bytes); > +
Who is going to take ownership of this memory? The contents of clover::module::section are supposed to be a self-contained data structure in a form that can be passed around, serialized and deserialized (using clCreateProgramWithBinary). That's not going to work if you stick pointers into it. It should be as simple as: | header.num_bytes = llvm_bitcode.size(); | sec.data.insert(sec.data.end(), (char *)header, | (char *)header + sizeof(header)); | sec.data.insert(sec.data.end(), llvm_bitcode.begin(), | llvm_bitcode.end()); > + 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)); > + } > + } > + m.syms.push_back(module::symbol(kernel_name, 0, 0, args )); > + m.secs.push_back(module::section(0, module::section::text, > + sizeof(struct pipe_compute_program), > + compat::vector<char>((char *)program, > + sizeof(struct > pipe_compute_program)))); > + 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); > + } > }
pgpI4pAkRgSNr.pgp
Description: PGP signature
_______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev