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