[email protected] writes: > From: Tom Stellard <[email protected]> > > 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 [email protected] http://lists.freedesktop.org/mailman/listinfo/mesa-dev
