1f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// 2f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// Copyright 2012 Francisco Jerez 3f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// 4f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// Permission is hereby granted, free of charge, to any person obtaining a 5f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// copy of this software and associated documentation files (the "Software"), 6f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// to deal in the Software without restriction, including without limitation 7f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// the rights to use, copy, modify, merge, publish, distribute, sublicense, 8f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// and/or sell copies of the Software, and to permit persons to whom the 9f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// Software is furnished to do so, subject to the following conditions: 10f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// 11f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// The above copyright notice and this permission notice shall be included in 12f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// all copies or substantial portions of the Software. 13f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// 14f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 18f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF 19f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// SOFTWARE. 21f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org// 22f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 23f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "core/compiler.hpp" 24f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 25f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include <clang/Frontend/CompilerInstance.h> 26f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include <clang/Frontend/TextDiagnosticPrinter.h> 27f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include <clang/CodeGen/CodeGenAction.h> 28f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include <llvm/Bitcode/BitstreamWriter.h> 29f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include <llvm/Bitcode/ReaderWriter.h> 30f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include <llvm/DerivedTypes.h> 31f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include <llvm/Linker.h> 32f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include <llvm/LLVMContext.h> 33f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include <llvm/Module.h> 34f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include <llvm/PassManager.h> 35f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include <llvm/Support/TargetSelect.h> 36f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include <llvm/Support/MemoryBuffer.h> 37f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include <llvm/Support/PathV1.h> 38f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include <llvm/Target/TargetData.h> 39f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include <llvm/Transforms/IPO.h> 40f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include <llvm/Transforms/IPO/PassManagerBuilder.h> 41f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 42f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "pipe/p_state.h" 43f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "util/u_memory.h" 44f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 45f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include <iostream> 46f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include <iomanip> 47f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include <fstream> 48f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include <cstdio> 49f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 50f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgusing namespace clover; 51f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 52f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgnamespace { 53f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#if 0 54f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org void 55f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org build_binary(const std::string &source, const std::string &target, 56f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const std::string &name) { 57f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org clang::CompilerInstance c; 58f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org clang::EmitObjAction act(&llvm::getGlobalContext()); 59f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org std::string log; 60f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org llvm::raw_string_ostream s_log(log); 61f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 62f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org LLVMInitializeTGSITarget(); 63f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org LLVMInitializeTGSITargetInfo(); 64f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org LLVMInitializeTGSITargetMC(); 65f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org LLVMInitializeTGSIAsmPrinter(); 66f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 67f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org c.getFrontendOpts().Inputs.push_back( 68f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org std::make_pair(clang::IK_OpenCL, name)); 69f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org c.getHeaderSearchOpts().UseBuiltinIncludes = false; 70f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org c.getHeaderSearchOpts().UseStandardIncludes = false; 71f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org c.getLangOpts().NoBuiltin = true; 72f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org c.getTargetOpts().Triple = target; 73f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org c.getInvocation().setLangDefaults(clang::IK_OpenCL); 74f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org c.createDiagnostics(0, NULL, new clang::TextDiagnosticPrinter( 75f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org s_log, c.getDiagnosticOpts())); 76f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 77f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org c.getPreprocessorOpts().addRemappedFile( 78f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org name, llvm::MemoryBuffer::getMemBuffer(source)); 79f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 80f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (!c.ExecuteAction(act)) 81f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org throw build_error(log); 82f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 83f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 84f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org module 85f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org load_binary(const char *name) { 86f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org std::ifstream fs((name)); 87f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org std::vector<unsigned char> str((std::istreambuf_iterator<char>(fs)), 88f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org (std::istreambuf_iterator<char>())); 89f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org compat::istream cs(str); 90f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return module::deserialize(cs); 91f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 92f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif 93f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 94f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org llvm::Module * 95f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org compile(const std::string &source, const std::string &name, 96f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const std::string &triple) { 97f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 98f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org clang::CompilerInstance c; 99f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org clang::EmitLLVMOnlyAction act(&llvm::getGlobalContext()); 100f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org std::string log; 101f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org llvm::raw_string_ostream s_log(log); 102f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 103f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org c.getFrontendOpts().Inputs.push_back( 104f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org clang::FrontendInputFile(name, clang::IK_OpenCL)); 105f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org c.getFrontendOpts().ProgramAction = clang::frontend::EmitLLVMOnly; 106f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org c.getHeaderSearchOpts().UseBuiltinIncludes = true; 107f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org c.getHeaderSearchOpts().UseStandardSystemIncludes = true; 108f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org c.getHeaderSearchOpts().ResourceDir = CLANG_RESOURCE_DIR; 109f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 110f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // Add libclc generic search path 111f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org c.getHeaderSearchOpts().AddPath(LIBCLC_INCLUDEDIR, 112f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org clang::frontend::Angled, 113f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org false, false, false); 114f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 115f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // Add libclc include 116f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org c.getPreprocessorOpts().Includes.push_back("clc/clc.h"); 117f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 118f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // clc.h requires that this macro be defined: 119f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org c.getPreprocessorOpts().addMacroDef("cl_clang_storage_class_specifiers"); 120f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 121f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org c.getLangOpts().NoBuiltin = true; 122f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org c.getTargetOpts().Triple = triple; 123f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org c.getInvocation().setLangDefaults(clang::IK_OpenCL); 124f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org c.createDiagnostics(0, NULL, new clang::TextDiagnosticPrinter( 125f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org s_log, c.getDiagnosticOpts())); 126f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 127f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org c.getPreprocessorOpts().addRemappedFile(name, 128f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org llvm::MemoryBuffer::getMemBuffer(source)); 129f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 130f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // Compile the code 131f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (!c.ExecuteAction(act)) 132f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org throw build_error(log); 133f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 134f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return act.takeModule(); 135f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 136f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 137f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org void 138f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org find_kernels(llvm::Module *mod, std::vector<llvm::Function *> &kernels) { 139f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const llvm::NamedMDNode *kernel_node = 140f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org mod->getNamedMetadata("opencl.kernels"); 141f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org for (unsigned i = 0; i < kernel_node->getNumOperands(); ++i) { 142f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org kernels.push_back(llvm::dyn_cast<llvm::Function>( 143f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org kernel_node->getOperand(i)->getOperand(0))); 144f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 145f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 146f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 147f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org void 148f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org link(llvm::Module *mod, const std::string &triple, 149f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const std::vector<llvm::Function *> &kernels) { 150f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 151f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org llvm::PassManager PM; 152f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org llvm::PassManagerBuilder Builder; 153f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org bool isNative; 154f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org llvm::Linker linker("clover", mod); 155f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 156f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // Link the kernel with libclc 157f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org linker.LinkInFile(llvm::sys::Path(LIBCLC_LIBEXECDIR + triple + ".bc"), isNative); 158f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org mod = linker.releaseModule(); 159f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 160f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // Add a function internalizer pass. 161f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // 162f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // By default, the function internalizer pass will look for a function 163f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // called "main" and then mark all other functions as internal. Marking 164f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // functions as internal enables the optimizer to perform optimizations 165f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // like function inlining and global dead-code elimination. 166f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // 167f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // When there is no "main" function in a module, the internalize pass will 168f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // treat the module like a library, and it won't internalize any functions. 169f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // Since there is no "main" function in our kernels, we need to tell 170f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // the internalizer pass that this module is not a library by passing a 171f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // list of kernel functions to the internalizer. The internalizer will 172f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // treat the functions in the list as "main" functions and internalize 173f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // all of the other functions. 174f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org std::vector<const char*> export_list; 175f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org for (std::vector<llvm::Function *>::const_iterator I = kernels.begin(), 176f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org E = kernels.end(); 177f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org I != E; ++I) { 178f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org llvm::Function *kernel = *I; 179f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org export_list.push_back(kernel->getName().data()); 180f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 181f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org PM.add(llvm::createInternalizePass(export_list)); 182f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 183f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // Run link time optimizations 184f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Builder.OptLevel = 2; 185f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org Builder.populateLTOPassManager(PM, false, true); 186f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org PM.run(*mod); 187f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 188f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 189f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org module 190f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org build_module_llvm(llvm::Module *mod, 191f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const std::vector<llvm::Function *> &kernels) { 192f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 193f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org module m; 194f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org struct pipe_llvm_program_header header; 195f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 196f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org llvm::SmallVector<char, 1024> llvm_bitcode; 197f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org llvm::raw_svector_ostream bitcode_ostream(llvm_bitcode); 198f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org llvm::BitstreamWriter writer(llvm_bitcode); 199f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org llvm::WriteBitcodeToFile(mod, bitcode_ostream); 200f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org bitcode_ostream.flush(); 201f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 202f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org llvm::Function *kernel_func; 203f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org std::string kernel_name; 204f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org compat::vector<module::argument> args; 205f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 206f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // XXX: Support more than one kernel 207f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org assert(kernels.size() == 1); 208f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 209f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org kernel_func = kernels[0]; 210f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org kernel_name = kernel_func->getName(); 211f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 212f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org for (llvm::Function::arg_iterator I = kernel_func->arg_begin(), 213f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org E = kernel_func->arg_end(); I != E; ++I) { 214f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org llvm::Argument &arg = *I; 215f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org llvm::Type *arg_type = arg.getType(); 216f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org llvm::TargetData TD(kernel_func->getParent()); 217f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org unsigned arg_size = TD.getTypeStoreSize(arg_type); 218f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 219f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (llvm::isa<llvm::PointerType>(arg_type) && arg.hasByValAttr()) { 220f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org arg_type = 221f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org llvm::dyn_cast<llvm::PointerType>(arg_type)->getElementType(); 222f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 223f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 224f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (arg_type->isPointerTy()) { 225f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // XXX: Figure out LLVM->OpenCL address space mappings for each 226f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // target. I think we need to ask clang what these are. For now, 227f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // pretend everything is in the global address space. 228f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org unsigned address_space = llvm::cast<llvm::PointerType>(arg_type)->getAddressSpace(); 229f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org switch (address_space) { 230f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org default: 231f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org args.push_back(module::argument(module::argument::global, arg_size)); 232f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org break; 233f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 234f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } else { 235f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org args.push_back(module::argument(module::argument::scalar, arg_size)); 236f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 237f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 238f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 239f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org header.num_bytes = llvm_bitcode.size(); 240f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org std::string data; 241f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org data.insert(0, (char*)(&header), sizeof(header)); 242f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org data.insert(data.end(), llvm_bitcode.begin(), 243f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org llvm_bitcode.end()); 244f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org m.syms.push_back(module::symbol(kernel_name, 0, 0, args )); 245f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org m.secs.push_back(module::section(0, module::section::text, 246f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org header.num_bytes, data)); 247f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 248f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return m; 249f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 250f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} // End anonymous namespace 251f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 252f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgmodule 253f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgclover::compile_program_llvm(const compat::string &source, 254f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org enum pipe_shader_ir ir, 255f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const compat::string &triple) { 256f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 257f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org std::vector<llvm::Function *> kernels; 258f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 259f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org llvm::Module *mod = compile(source, "cl_input", triple); 260f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 261f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org find_kernels(mod, kernels); 262f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 263f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org link(mod, triple, kernels); 264f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 265f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org // Build the clover::module 266f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org switch (ir) { 267f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org case PIPE_SHADER_IR_TGSI: 268f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org //XXX: Handle TGSI 269f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org assert(0); 270f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return module(); 271f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org default: 272f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return build_module_llvm(mod, kernels); 273f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 274f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 275