1c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez// 2c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez// Copyright 2012 Francisco Jerez 3c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez// 4c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez// Permission is hereby granted, free of charge, to any person obtaining a 5c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez// copy of this software and associated documentation files (the "Software"), 6c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez// to deal in the Software without restriction, including without limitation 7c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez// the rights to use, copy, modify, merge, publish, distribute, sublicense, 8c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez// and/or sell copies of the Software, and to permit persons to whom the 9c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez// Software is furnished to do so, subject to the following conditions: 10c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez// 11c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez// The above copyright notice and this permission notice shall be included in 12c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez// all copies or substantial portions of the Software. 13c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez// 14c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez// THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 18c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF 19c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez// OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez// SOFTWARE. 21c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez// 22c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez 23c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez#include "core/compiler.hpp" 24c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez 25c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez#include <clang/Frontend/CompilerInstance.h> 26c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez#include <clang/Frontend/TextDiagnosticPrinter.h> 27c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez#include <clang/CodeGen/CodeGenAction.h> 2846a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard#include <llvm/Bitcode/BitstreamWriter.h> 2946a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard#include <llvm/Bitcode/ReaderWriter.h> 3046a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard#include <llvm/DerivedTypes.h> 3146a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard#include <llvm/Linker.h> 32c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez#include <llvm/LLVMContext.h> 3346a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard#include <llvm/Module.h> 3446a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard#include <llvm/PassManager.h> 35c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez#include <llvm/Support/TargetSelect.h> 36c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez#include <llvm/Support/MemoryBuffer.h> 3746a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard#include <llvm/Support/PathV1.h> 3846a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard#include <llvm/Target/TargetData.h> 39ca8fa0230896727af81ee54197f6e2233d49481dTom Stellard#include <llvm/Transforms/IPO.h> 4046a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard#include <llvm/Transforms/IPO/PassManagerBuilder.h> 4146a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard 4246a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard#include "pipe/p_state.h" 4346a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard#include "util/u_memory.h" 44c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez 45c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez#include <iostream> 46c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez#include <iomanip> 47c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez#include <fstream> 48c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez#include <cstdio> 49c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez 50c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerezusing namespace clover; 51c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez 52c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jereznamespace { 5346a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard#if 0 54c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez void 55c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez build_binary(const std::string &source, const std::string &target, 56c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez const std::string &name) { 57c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez clang::CompilerInstance c; 58c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez clang::EmitObjAction act(&llvm::getGlobalContext()); 59c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez std::string log; 60c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez llvm::raw_string_ostream s_log(log); 61c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez 62c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez LLVMInitializeTGSITarget(); 63c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez LLVMInitializeTGSITargetInfo(); 64c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez LLVMInitializeTGSITargetMC(); 65c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez LLVMInitializeTGSIAsmPrinter(); 66c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez 67c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez c.getFrontendOpts().Inputs.push_back( 68c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez std::make_pair(clang::IK_OpenCL, name)); 69c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez c.getHeaderSearchOpts().UseBuiltinIncludes = false; 70c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez c.getHeaderSearchOpts().UseStandardIncludes = false; 71c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez c.getLangOpts().NoBuiltin = true; 72c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez c.getTargetOpts().Triple = target; 73c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez c.getInvocation().setLangDefaults(clang::IK_OpenCL); 74c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez c.createDiagnostics(0, NULL, new clang::TextDiagnosticPrinter( 75c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez s_log, c.getDiagnosticOpts())); 76c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez 77c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez c.getPreprocessorOpts().addRemappedFile( 78c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez name, llvm::MemoryBuffer::getMemBuffer(source)); 79c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez 80c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez if (!c.ExecuteAction(act)) 81c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez throw build_error(log); 82c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez } 83c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez 84c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez module 85c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez load_binary(const char *name) { 86c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez std::ifstream fs((name)); 87c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez std::vector<unsigned char> str((std::istreambuf_iterator<char>(fs)), 88c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez (std::istreambuf_iterator<char>())); 89c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez compat::istream cs(str); 90c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez return module::deserialize(cs); 91c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez } 92c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez#endif 93c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez 9446a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard llvm::Module * 9546a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard compile(const std::string &source, const std::string &name, 9646a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard const std::string &triple) { 9746a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard 9846a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard clang::CompilerInstance c; 9946a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard clang::EmitLLVMOnlyAction act(&llvm::getGlobalContext()); 10046a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard std::string log; 10146a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard llvm::raw_string_ostream s_log(log); 10246a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard 10346a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard c.getFrontendOpts().Inputs.push_back( 10446a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard clang::FrontendInputFile(name, clang::IK_OpenCL)); 10546a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard c.getFrontendOpts().ProgramAction = clang::frontend::EmitLLVMOnly; 10646a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard c.getHeaderSearchOpts().UseBuiltinIncludes = true; 10746a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard c.getHeaderSearchOpts().UseStandardSystemIncludes = true; 10846a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard c.getHeaderSearchOpts().ResourceDir = CLANG_RESOURCE_DIR; 10946a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard 11046a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard // Add libclc generic search path 11139fdab1d66bd3374c6de31bb8d890b911391c1faJohannes Obermayr c.getHeaderSearchOpts().AddPath(LIBCLC_INCLUDEDIR, 11246a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard clang::frontend::Angled, 11346a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard false, false, false); 11446a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard 11546a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard // Add libclc include 11646a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard c.getPreprocessorOpts().Includes.push_back("clc/clc.h"); 11746a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard 11846a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard // clc.h requires that this macro be defined: 11946a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard c.getPreprocessorOpts().addMacroDef("cl_clang_storage_class_specifiers"); 12046a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard 12146a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard c.getLangOpts().NoBuiltin = true; 12246a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard c.getTargetOpts().Triple = triple; 12346a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard c.getInvocation().setLangDefaults(clang::IK_OpenCL); 12446a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard c.createDiagnostics(0, NULL, new clang::TextDiagnosticPrinter( 12546a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard s_log, c.getDiagnosticOpts())); 12646a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard 12746a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard c.getPreprocessorOpts().addRemappedFile(name, 12846a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard llvm::MemoryBuffer::getMemBuffer(source)); 12946a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard 13046a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard // Compile the code 13146a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard if (!c.ExecuteAction(act)) 13246a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard throw build_error(log); 13346a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard 13446a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard return act.takeModule(); 13546a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard } 13646a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard 13746a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard void 138ca8fa0230896727af81ee54197f6e2233d49481dTom Stellard find_kernels(llvm::Module *mod, std::vector<llvm::Function *> &kernels) { 139ca8fa0230896727af81ee54197f6e2233d49481dTom Stellard const llvm::NamedMDNode *kernel_node = 140ca8fa0230896727af81ee54197f6e2233d49481dTom Stellard mod->getNamedMetadata("opencl.kernels"); 141ca8fa0230896727af81ee54197f6e2233d49481dTom Stellard for (unsigned i = 0; i < kernel_node->getNumOperands(); ++i) { 142ca8fa0230896727af81ee54197f6e2233d49481dTom Stellard kernels.push_back(llvm::dyn_cast<llvm::Function>( 143ca8fa0230896727af81ee54197f6e2233d49481dTom Stellard kernel_node->getOperand(i)->getOperand(0))); 144ca8fa0230896727af81ee54197f6e2233d49481dTom Stellard } 145ca8fa0230896727af81ee54197f6e2233d49481dTom Stellard } 146ca8fa0230896727af81ee54197f6e2233d49481dTom Stellard 147ca8fa0230896727af81ee54197f6e2233d49481dTom Stellard void 148ca8fa0230896727af81ee54197f6e2233d49481dTom Stellard link(llvm::Module *mod, const std::string &triple, 149ca8fa0230896727af81ee54197f6e2233d49481dTom Stellard const std::vector<llvm::Function *> &kernels) { 15046a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard 15146a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard llvm::PassManager PM; 15246a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard llvm::PassManagerBuilder Builder; 15346a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard bool isNative; 15446a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard llvm::Linker linker("clover", mod); 15546a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard 15646a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard // Link the kernel with libclc 15739fdab1d66bd3374c6de31bb8d890b911391c1faJohannes Obermayr linker.LinkInFile(llvm::sys::Path(LIBCLC_LIBEXECDIR + triple + ".bc"), isNative); 15846a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard mod = linker.releaseModule(); 15946a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard 160ca8fa0230896727af81ee54197f6e2233d49481dTom Stellard // Add a function internalizer pass. 161ca8fa0230896727af81ee54197f6e2233d49481dTom Stellard // 162ca8fa0230896727af81ee54197f6e2233d49481dTom Stellard // By default, the function internalizer pass will look for a function 163ca8fa0230896727af81ee54197f6e2233d49481dTom Stellard // called "main" and then mark all other functions as internal. Marking 164ca8fa0230896727af81ee54197f6e2233d49481dTom Stellard // functions as internal enables the optimizer to perform optimizations 165ca8fa0230896727af81ee54197f6e2233d49481dTom Stellard // like function inlining and global dead-code elimination. 166ca8fa0230896727af81ee54197f6e2233d49481dTom Stellard // 167ca8fa0230896727af81ee54197f6e2233d49481dTom Stellard // When there is no "main" function in a module, the internalize pass will 168ca8fa0230896727af81ee54197f6e2233d49481dTom Stellard // treat the module like a library, and it won't internalize any functions. 169ca8fa0230896727af81ee54197f6e2233d49481dTom Stellard // Since there is no "main" function in our kernels, we need to tell 170ca8fa0230896727af81ee54197f6e2233d49481dTom Stellard // the internalizer pass that this module is not a library by passing a 171ca8fa0230896727af81ee54197f6e2233d49481dTom Stellard // list of kernel functions to the internalizer. The internalizer will 172ca8fa0230896727af81ee54197f6e2233d49481dTom Stellard // treat the functions in the list as "main" functions and internalize 173ca8fa0230896727af81ee54197f6e2233d49481dTom Stellard // all of the other functions. 174ca8fa0230896727af81ee54197f6e2233d49481dTom Stellard std::vector<const char*> export_list; 175ca8fa0230896727af81ee54197f6e2233d49481dTom Stellard for (std::vector<llvm::Function *>::const_iterator I = kernels.begin(), 176ca8fa0230896727af81ee54197f6e2233d49481dTom Stellard E = kernels.end(); 177ca8fa0230896727af81ee54197f6e2233d49481dTom Stellard I != E; ++I) { 178ca8fa0230896727af81ee54197f6e2233d49481dTom Stellard llvm::Function *kernel = *I; 179ca8fa0230896727af81ee54197f6e2233d49481dTom Stellard export_list.push_back(kernel->getName().data()); 180ca8fa0230896727af81ee54197f6e2233d49481dTom Stellard } 181ca8fa0230896727af81ee54197f6e2233d49481dTom Stellard PM.add(llvm::createInternalizePass(export_list)); 182ca8fa0230896727af81ee54197f6e2233d49481dTom Stellard 18346a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard // Run link time optimizations 18446a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard Builder.OptLevel = 2; 185ca8fa0230896727af81ee54197f6e2233d49481dTom Stellard Builder.populateLTOPassManager(PM, false, true); 18646a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard PM.run(*mod); 18746a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard } 18846a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard 18946a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard module 190ca8fa0230896727af81ee54197f6e2233d49481dTom Stellard build_module_llvm(llvm::Module *mod, 191ca8fa0230896727af81ee54197f6e2233d49481dTom Stellard const std::vector<llvm::Function *> &kernels) { 19246a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard 19346a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard module m; 19446a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard struct pipe_llvm_program_header header; 19546a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard 19646a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard llvm::SmallVector<char, 1024> llvm_bitcode; 19746a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard llvm::raw_svector_ostream bitcode_ostream(llvm_bitcode); 19846a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard llvm::BitstreamWriter writer(llvm_bitcode); 19946a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard llvm::WriteBitcodeToFile(mod, bitcode_ostream); 20046a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard bitcode_ostream.flush(); 20146a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard 202ca8fa0230896727af81ee54197f6e2233d49481dTom Stellard llvm::Function *kernel_func; 20346a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard std::string kernel_name; 20446a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard compat::vector<module::argument> args; 205ca8fa0230896727af81ee54197f6e2233d49481dTom Stellard 20646a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard // XXX: Support more than one kernel 207ca8fa0230896727af81ee54197f6e2233d49481dTom Stellard assert(kernels.size() == 1); 20846a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard 209ca8fa0230896727af81ee54197f6e2233d49481dTom Stellard kernel_func = kernels[0]; 21046a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard kernel_name = kernel_func->getName(); 21146a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard 21246a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard for (llvm::Function::arg_iterator I = kernel_func->arg_begin(), 21346a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard E = kernel_func->arg_end(); I != E; ++I) { 21446a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard llvm::Argument &arg = *I; 21546a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard llvm::Type *arg_type = arg.getType(); 21646a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard llvm::TargetData TD(kernel_func->getParent()); 21746a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard unsigned arg_size = TD.getTypeStoreSize(arg_type); 21846a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard 21946a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard if (llvm::isa<llvm::PointerType>(arg_type) && arg.hasByValAttr()) { 22046a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard arg_type = 22146a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard llvm::dyn_cast<llvm::PointerType>(arg_type)->getElementType(); 22246a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard } 22346a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard 22446a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard if (arg_type->isPointerTy()) { 22546a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard // XXX: Figure out LLVM->OpenCL address space mappings for each 22646a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard // target. I think we need to ask clang what these are. For now, 22746a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard // pretend everything is in the global address space. 22846a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard unsigned address_space = llvm::cast<llvm::PointerType>(arg_type)->getAddressSpace(); 22946a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard switch (address_space) { 23046a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard default: 23146a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard args.push_back(module::argument(module::argument::global, arg_size)); 23246a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard break; 23346a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard } 23446a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard } else { 23546a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard args.push_back(module::argument(module::argument::scalar, arg_size)); 23646a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard } 23746a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard } 23846a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard 23946a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard header.num_bytes = llvm_bitcode.size(); 24046a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard std::string data; 24146a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard data.insert(0, (char*)(&header), sizeof(header)); 24246a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard data.insert(data.end(), llvm_bitcode.begin(), 24346a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard llvm_bitcode.end()); 24446a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard m.syms.push_back(module::symbol(kernel_name, 0, 0, args )); 24546a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard m.secs.push_back(module::section(0, module::section::text, 24646a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard header.num_bytes, data)); 24746a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard 24846a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard return m; 24946a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard } 25046a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard} // End anonymous namespace 25146a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard 252c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerezmodule 253c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerezclover::compile_program_llvm(const compat::string &source, 25446a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard enum pipe_shader_ir ir, 25546a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard const compat::string &triple) { 25646a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard 257ca8fa0230896727af81ee54197f6e2233d49481dTom Stellard std::vector<llvm::Function *> kernels; 258ca8fa0230896727af81ee54197f6e2233d49481dTom Stellard 25946a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard llvm::Module *mod = compile(source, "cl_input", triple); 26046a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard 261ca8fa0230896727af81ee54197f6e2233d49481dTom Stellard find_kernels(mod, kernels); 262ca8fa0230896727af81ee54197f6e2233d49481dTom Stellard 263ca8fa0230896727af81ee54197f6e2233d49481dTom Stellard link(mod, triple, kernels); 26446a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard 26546a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard // Build the clover::module 26646a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard switch (ir) { 26746a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard case PIPE_SHADER_IR_TGSI: 26846a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard //XXX: Handle TGSI 26946a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard assert(0); 27046a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard return module(); 27146a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard default: 272ca8fa0230896727af81ee54197f6e2233d49481dTom Stellard return build_module_llvm(mod, kernels); 27346a13b3b11d859e131399853c11ae2be0eb02f0aTom Stellard } 274c6db1b3396384186aab5b685fe1fd540e17b3a62Francisco Jerez} 275