aboutsummaryrefslogtreecommitdiff
path: root/clocl
diff options
context:
space:
mode:
authorGil Pitney <gil.pitney@linaro.org>2014-10-28 18:00:42 -0700
committerGil Pitney <gil.pitney@linaro.org>2014-10-28 18:00:42 -0700
commit61b2c94d9e64758e55730be6a3fc9006c171db85 (patch)
treef564f09ebf93ba293dfa225bd374df6f1f37aa01 /clocl
Initial Commit: Based on TI OpenCL v0.8, originally based on clover.shamrock_v0.8
This is a continuation of the clover OpenCL project: http://people.freedesktop.org/~steckdenis/clover based on the contributions from Texas Instruments for Keystone II DSP device: git.ti.com/opencl and adding contributions from Linaro for ARM CPU-only support. See README.txt for more info, and build instructions. Signed-off-by: Gil Pitney <gil.pitney@linaro.org>
Diffstat (limited to 'clocl')
-rw-r--r--clocl/.gitignore1
-rw-r--r--clocl/CMakeLists.txt14
-rw-r--r--clocl/Makefile100
-rw-r--r--clocl/compiler.cpp270
-rw-r--r--clocl/compiler.h126
-rw-r--r--clocl/file_manip.cpp46
-rw-r--r--clocl/file_manip.h12
-rw-r--r--clocl/main.cpp396
-rw-r--r--clocl/options.cpp223
-rw-r--r--clocl/options.h24
-rw-r--r--clocl/program.cpp189
11 files changed, 1401 insertions, 0 deletions
diff --git a/clocl/.gitignore b/clocl/.gitignore
new file mode 100644
index 0000000..5761abc
--- /dev/null
+++ b/clocl/.gitignore
@@ -0,0 +1 @@
+*.o
diff --git a/clocl/CMakeLists.txt b/clocl/CMakeLists.txt
new file mode 100644
index 0000000..e5eec38
--- /dev/null
+++ b/clocl/CMakeLists.txt
@@ -0,0 +1,14 @@
+if (SHANNON_BUILD OR HAWKING_CROSS_COMPILE)
+ add_custom_command(OUTPUT x86/clocl COMMAND make -j4
+ WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
+ add_custom_target(x86_clocl DEPENDS x86/clocl)
+ set(CROSS_TARGET cross)
+ install(PROGRAMS x86/clocl DESTINATION bin/x86 ${OCL_BPERMS})
+endif()
+
+if (HAWKING_BUILD)
+ add_custom_command(OUTPUT arm/clocl COMMAND make -j4 ${CROSS_TARGET} TARGET=arm
+ WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
+ add_custom_target(arm_clocl DEPENDS arm/clocl)
+ install(PROGRAMS arm/clocl DESTINATION bin/arm ${OCL_BPERMS})
+endif()
diff --git a/clocl/Makefile b/clocl/Makefile
new file mode 100644
index 0000000..4ffccb7
--- /dev/null
+++ b/clocl/Makefile
@@ -0,0 +1,100 @@
+# If not specified, pick a default location for dependent llvm libraries
+LLVM_VERSION = 33
+
+ifeq ($(DEFAULT_DEV_INSTALL_DIR),)
+ DEFAULT_DEV_INSTALL_DIR = /opt/ti
+endif
+
+ifeq ($(ARM_LLVM_DIR),)
+ ARM_LLVM_DIR = $(DEFAULT_DEV_INSTALL_DIR)/llvm$(LLVM_VERSION)-install-arm
+endif
+
+ifeq ($(X86_LLVM_DIR),)
+ X86_LLVM_DIR = $(DEFAULT_DEV_INSTALL_DIR)/llvm$(LLVM_VERSION)-install-x86
+endif
+
+CLANG_LIBS = -lclangFrontendTool
+CLANG_LIBS += -lclangFrontend
+CLANG_LIBS += -lclangDriver
+CLANG_LIBS += -lclangSerialization
+CLANG_LIBS += -lclangCodeGen
+CLANG_LIBS += -lclangParse
+CLANG_LIBS += -lclangSema
+CLANG_LIBS += -lclangEdit
+CLANG_LIBS += -lclangAnalysis
+CLANG_LIBS += -lclangAST
+CLANG_LIBS += -lclangLex
+CLANG_LIBS += -lclangBasic
+
+
+EXE = clocl
+
+UNAME_M :=$(shell uname -m)
+ifneq (,$(findstring 86, $(UNAME_M)))
+ BUILD_PROCESSOR := x86
+ TARGET := x86
+ LLVM_DIR := $(X86_LLVM_DIR)
+ CXX := g++ -m32
+else ifneq (,$(findstring arm, $(UNAME_M)))
+ BUILD_PROCESSOR := arm
+ TARGET := arm
+ LLVM_DIR := $(ARM_LLVM_DIR)
+ CXX := g++
+endif
+
+LLVM_CONFIG_EXECUTABLE = $(LLVM_DIR)/bin/llvm-config
+LLVM_CXXFLAGS = `${LLVM_CONFIG_EXECUTABLE} --cxxflags `
+LLVM_LDFLAGS = -L $(LLVM_DIR)/lib -lpthread -lrt -ldl -lm
+LLVM_LIBS = `${LLVM_CONFIG_EXECUTABLE} --libs ${TARGET} asmparser bitwriter tablegen mcjit debuginfo interpreter irreader jit linker instrumentation ipo mcdisassembler`
+
+# If Cross Compiling for ARM override some make variables
+cross: override CXX=arm-linux-gnueabihf-g++
+cross: override TARGET=arm
+cross: override LLVM_CONFIG_EXECUTABLE=$(ARM_LLVM_DIR)/bin/llvm-config-host
+cross: override LLVM_LDFLAGS=-L $(ARM_LLVM_DIR)/lib -lpthread -lrt -ldl -lm
+# Need to explicitly add /usr/include when cross compiling to pick up
+# dependent 3rd party non-system headers
+cross: override HOST_USR_INCLUDE=-I/usr/include
+
+
+WGADIR = ../src/core/dsp
+POCLDIR = ../src/llvmopencl
+OBJS = AllocasToEntry.o BarrierBlock.o BarrierTailReplication.o \
+ BreakConstantGEPs.o CanonicalizeBarriers.o Flatten.o \
+ GenerateHeader.o ImplicitLoopBarriers.o IsolateRegions.o \
+ Kernel.o LLVMUtils.o LoopBarriers.o ParallelRegion.o \
+ PHIsToAllocas.o TargetAddressSpaces.o \
+ VariableUniformityAnalysis.o WIVectorize.o Workgroup.o \
+ WorkItemAliasAnalysis.o WorkitemHandler.o \
+ WorkitemHandlerChooser.o WorkitemLoops.o WorkitemReplication.o\
+ main.o compiler.o wga.o program.o file_manip.o options.o
+
+OBJS := $(patsubst %.o, $(TARGET)/%.o, $(OBJS))
+
+CXXFLAGS = ${LLVM_CXXFLAGS} -I${WGADIR} -I${POCLDIR} \
+ ${HOST_USR_INCLUDE} -O3 -fexceptions
+LIBS = ${CLANG_LIBS} ${LLVM_LIBS}
+LDFLAGS = ${LLVM_LDFLAGS}
+
+$(EXE): ${OBJS}
+ $(CXX) $^ $(LIBS) $(LDFLAGS) -o $(TARGET)/$@
+
+cross: $(EXE)
+
+$(TARGET)/%.o: %.cpp | $(TARGET)/
+ $(CXX) $(CXXFLAGS) -c $< -o $@
+
+$(TARGET)/%.o: ${WGADIR}/%.cpp | $(TARGET)/
+ $(CXX) $(CXXFLAGS) -c $< -o $@
+
+$(TARGET)/%.o: ${POCLDIR}/%.cpp | $(TARGET)/
+ $(CXX) $(CXXFLAGS) -c $< -o $@
+
+$(TARGET)/%.o: ${POCLDIR}/%.cc | $(TARGET)/
+ $(CXX) $(CXXFLAGS) -c $< -o $@
+
+$(TARGET)/:
+ mkdir -p $@
+
+clean:
+ rm -f x86/* arm/*
diff --git a/clocl/compiler.cpp b/clocl/compiler.cpp
new file mode 100644
index 0000000..90ff0ae
--- /dev/null
+++ b/clocl/compiler.cpp
@@ -0,0 +1,270 @@
+/*
+ * Copyright (c) 2011, Denis Steckelmacher <steckdenis@yahoo.fr>
+ * Copyright (c) 2013-2014, Texas Instruments Incorporated - http://www.ti.com/
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the copyright holder nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * \file compiler.cpp
+ * \brief Compiler wrapper around Clang
+ */
+
+#include "compiler.h"
+#include "options.h"
+
+#include <cstring>
+#include <string>
+#include <sstream>
+#include <iostream>
+#include <clang/Frontend/CompilerInvocation.h>
+#include <clang/Frontend/TextDiagnosticPrinter.h>
+#include <clang/Frontend/LangStandard.h>
+#include <clang/Basic/Diagnostic.h>
+#include <clang/CodeGen/CodeGenAction.h>
+#include <llvm/ADT/SmallVector.h>
+#include <llvm/Support/Host.h>
+#include <llvm/Support/MemoryBuffer.h> // ASW
+#include <llvm/IR/Module.h>
+#include <llvm/IR/LLVMContext.h>
+
+std::string get_ocl_dsp();
+
+Compiler::Compiler()
+: p_module(0), p_optimize(true), p_log_stream(p_log),
+ p_log_printer(0)
+{
+}
+
+Compiler::~Compiler()
+{
+
+}
+
+bool Compiler::compile(const std::string &options,
+ llvm::MemoryBuffer *source,
+ std::string filename)
+{
+ /* Set options */
+ p_options = options;
+
+ clang::CodeGenOptions &codegen_opts = p_compiler.getCodeGenOpts();
+ clang::DiagnosticOptions &diag_opts = p_compiler.getDiagnosticOpts();
+ clang::FrontendOptions &frontend_opts = p_compiler.getFrontendOpts();
+ clang::HeaderSearchOptions &header_opts = p_compiler.getHeaderSearchOpts();
+ clang::LangOptions &lang_opts = p_compiler.getLangOpts();
+ clang::TargetOptions &target_opts = p_compiler.getTargetOpts();
+ clang::PreprocessorOptions &prep_opts = p_compiler.getPreprocessorOpts();
+ clang::CompilerInvocation &invocation = p_compiler.getInvocation();
+
+ // Set codegen options
+ codegen_opts.setDebugInfo(clang::CodeGenOptions::NoDebugInfo);
+ codegen_opts.AsmVerbose = true;
+
+ // level 3 is too much for the pocl transformations.
+ codegen_opts.OptimizationLevel = 2;
+
+ // Set diagnostic options
+ diag_opts.Pedantic = true;
+ diag_opts.ShowColumn = true;
+ diag_opts.ShowLocation = true;
+ diag_opts.ShowCarets = false;
+ diag_opts.ShowFixits = true;
+ diag_opts.ShowColors = false;
+ diag_opts.ErrorLimit = 19;
+ diag_opts.MessageLength = 0;
+
+ // Set frontend options
+ frontend_opts.ProgramAction = clang::frontend::EmitLLVMOnly;
+ frontend_opts.DisableFree = true;
+
+ // Set header search options
+ header_opts.Verbose = false;
+ header_opts.UseBuiltinIncludes = false;
+ header_opts.UseStandardSystemIncludes = false;
+ header_opts.UseStandardCXXIncludes = false;
+
+ // Set preprocessor options
+ prep_opts.RetainRemappedFileBuffers = true;
+ if (!opt_builtin)
+ {
+ prep_opts.Includes.push_back("clc.h");
+ prep_opts.Includes.push_back("dsp.h");
+ }
+
+ // Set lang options
+ lang_opts.NoBuiltin = true;
+ lang_opts.OpenCL = true;
+ lang_opts.CPlusPlus = false;
+
+ // Set target options
+ // For 6X, use the 'spir' target as it implements opencl specs
+ target_opts.Triple = "spir-unknown-unknown-unknown";
+
+ // Currently, llp6x does not handle fused multiply and add
+ // llvm intrinsics (llvm.fmuladd.*). Disable generating these
+ // intrinsics using clang -ffp-contract=off option
+ codegen_opts.setFPContractMode(clang::CodeGenOptions::FPC_Off);
+
+ // Parse the user options
+ std::istringstream options_stream(options);
+ std::string token;
+ bool Werror = false, inI = false, inD = false;
+
+ /*-------------------------------------------------------------------------
+ * Add OpenCL C header path as a default location for searching for headers
+ *------------------------------------------------------------------------*/
+ header_opts.AddPath(get_ocl_dsp(), clang::frontend::Angled, false, false);
+
+ while (options_stream >> token)
+ {
+ if (inI)
+ {
+ // token is an include path
+ header_opts.AddPath(token, clang::frontend::Angled, false, false);
+ inI = false;
+ continue;
+ }
+ else if (inD)
+ {
+ // token is name or name=value
+ prep_opts.addMacroDef(token);
+ }
+
+ if (token == "-I")
+ {
+ inI = true;
+ }
+ else if (token == "-D")
+ {
+ inD = true;
+ }
+ else if (token == "-cl-single-precision-constant")
+ {
+ lang_opts.SinglePrecisionConstants = true;
+ }
+ else if (token == "-cl-opt-disable")
+ {
+ p_optimize = false;
+ codegen_opts.OptimizationLevel = 0;
+ }
+ else if (token == "-cl-mad-enable")
+ {
+ codegen_opts.LessPreciseFPMAD = true;
+ }
+ else if (token == "-cl-unsafe-math-optimizations")
+ {
+ codegen_opts.UnsafeFPMath = true;
+ }
+ else if (token == "-cl-finite-math-only")
+ {
+ codegen_opts.NoInfsFPMath = true;
+ codegen_opts.NoNaNsFPMath = true;
+ }
+ else if (token == "-cl-fast-relaxed-math")
+ {
+ codegen_opts.UnsafeFPMath = true;
+ codegen_opts.NoInfsFPMath = true;
+ codegen_opts.NoNaNsFPMath = true;
+ lang_opts.FastRelaxedMath = true;
+ }
+ else if (token == "-w")
+ {
+ diag_opts.IgnoreWarnings = true;
+ }
+ else if (token == "-Werror")
+ {
+ Werror = true;
+ }
+ }
+
+ // Set invocation options
+ //invocation.setLangDefaults(lang_opts,clang::IK_OpenCL);
+ invocation.setLangDefaults(lang_opts,clang::IK_OpenCL, clang::LangStandard::lang_opencl12);
+
+ // Create the diagnostics engine
+ p_log_printer = new clang::TextDiagnosticPrinter(p_log_stream, &diag_opts);
+ p_compiler.createDiagnostics(p_log_printer);
+
+ if (!p_compiler.hasDiagnostics())
+ return false;
+
+ p_compiler.getDiagnostics().setWarningsAsErrors(Werror);
+
+ // Feed the compiler with source
+ frontend_opts.Inputs.push_back(clang::FrontendInputFile(filename.c_str(), clang::IK_OpenCL));
+
+ std::string srcc = source->getBuffer();
+ const llvm::StringRef s_data(srcc);
+ const llvm::StringRef s_name("<source>");
+ llvm::MemoryBuffer *buffer =
+ llvm::MemoryBuffer::getMemBuffer(s_data, s_name);
+
+ prep_opts.addRemappedFile(filename.c_str(), buffer);
+
+ // Compile
+ llvm::OwningPtr<clang::CodeGenAction> act(
+ new clang::EmitLLVMOnlyAction(&llvm::getGlobalContext())
+ );
+
+ if (!p_compiler.ExecuteAction(*act))
+ {
+ // DEBUG
+ std::cout << log() << std::endl;
+ return false;
+ }
+
+ p_log_stream.flush();
+ p_module = act->takeModule();
+
+ // uncomment to debug the llvm IR
+ // p_module->dump();
+
+ return true;
+}
+
+const std::string &Compiler::log() const
+{
+ return p_log;
+}
+
+const std::string &Compiler::options() const
+{
+ return p_options;
+}
+
+bool Compiler::optimize() const
+{
+ return p_optimize;
+}
+
+llvm::Module *Compiler::module() const
+{
+ return p_module;
+}
+
+void Compiler::appendLog(const std::string &log)
+{
+ p_log += log;
+}
diff --git a/clocl/compiler.h b/clocl/compiler.h
new file mode 100644
index 0000000..2195cc2
--- /dev/null
+++ b/clocl/compiler.h
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2011, Denis Steckelmacher <steckdenis@yahoo.fr>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the copyright holder nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * \file compiler.h
+ * \brief Compiler wrapped around Clang
+ */
+
+#ifndef __COMPILER_H__
+#define __COMPILER_H__
+
+#include <string>
+
+#include <clang/Frontend/CompilerInstance.h>
+#include <llvm/Support/raw_ostream.h>
+
+namespace llvm
+{
+ class MemoryBuffer;
+ class Module;
+}
+
+namespace clang
+{
+ class TextDiagnosticPrinter;
+}
+
+
+/**
+ * \brief Compiler using Clang
+ *
+ * This class builds a Clang instance, runs it and then retains compilation logs
+ * and produced data.
+ */
+class Compiler
+{
+ public:
+ /**
+ * \brief Constructor
+ */
+ Compiler();
+ ~Compiler();
+
+ /**
+ * \brief Compile \p source to produce a LLVM module
+ * \param options options given to the compiler, described in the OpenCL spec
+ * \param source source to be compiled
+ * \return true if the compilation is successful, false otherwise
+ * \sa module()
+ * \sa log()
+ */
+ bool compile(const std::string &options, llvm::MemoryBuffer *source,
+ std::string filename);
+
+ /**
+ * \brief Compilation log
+ * \note \c appendLog() can also be used to append custom info at the end
+ * of the log, for instance to keep compilation and linking logs
+ * in the same place
+ * \return log
+ */
+ const std::string &log() const;
+
+ /**
+ * \brief Options given at \c compile()
+ * \return options used during compilation
+ */
+ const std::string &options() const;
+
+ /**
+ * \brief Optimization enabled
+ * \return true if -cl-opt-disable was given in the options, false otherwise
+ */
+ bool optimize() const;
+
+ /**
+ * \brief LLVM module generated
+ * \return LLVM module generated by the compilation, 0 if an error occured
+ */
+ llvm::Module *module() const;
+
+ /**
+ * \brief Append a string to the log
+ *
+ * This function can be used to append linking or code-gen logs to the
+ * internal compilation log kept by this class
+ *
+ * \param log log to be appended
+ */
+ void appendLog(const std::string &log);
+
+ private:
+ clang::CompilerInstance p_compiler;
+ llvm::Module *p_module;
+ bool p_optimize;
+
+ std::string p_log, p_options;
+ llvm::raw_string_ostream p_log_stream;
+ clang::TextDiagnosticPrinter *p_log_printer;
+};
+
+#endif
diff --git a/clocl/file_manip.cpp b/clocl/file_manip.cpp
new file mode 100644
index 0000000..5a51f16
--- /dev/null
+++ b/clocl/file_manip.cpp
@@ -0,0 +1,46 @@
+#include "file_manip.h"
+#include <unistd.h>
+
+bool fs_exists(std::string path)
+{
+ return (access(path.c_str(), F_OK) == 0);
+}
+
+std::string fs_filename(std::string path)
+{
+ int name_begin = path.rfind("/");
+ if (name_begin == std::string::npos) return path;
+ return path.substr(name_begin+1, path.size()-name_begin+1);
+}
+
+std::string fs_stem(std::string path)
+{
+ path = fs_filename(path);
+ int ext_begin = path.rfind(".");
+ if (ext_begin == std::string::npos) return path;
+ return path.substr(0, ext_begin);
+}
+
+std::string fs_ext(std::string path)
+{
+ int ext_begin = path.rfind(".");
+ if (ext_begin == std::string::npos) return "";
+ return path.substr(ext_begin, path.size()-ext_begin);
+}
+
+std::string fs_path(std::string path)
+{
+ int path_end = path.rfind("/");
+ if (path_end == std::string::npos) return "";
+ return path.substr(0, path_end+1);
+}
+
+std::string fs_replace_extension(std::string path, std::string ext)
+{
+ if (fs_ext(path) == "") return path;
+
+ path = fs_path(path) + fs_stem(path);
+
+ if (ext[0] == '.') return path + ext;
+ else return path + "." + ext;
+}
diff --git a/clocl/file_manip.h b/clocl/file_manip.h
new file mode 100644
index 0000000..7084239
--- /dev/null
+++ b/clocl/file_manip.h
@@ -0,0 +1,12 @@
+#ifndef _FILE_MANIP_H_
+#define _FILE_MANIP_H_
+#include <string>
+
+bool fs_exists (std::string path);
+std::string fs_filename (std::string path);
+std::string fs_stem (std::string path);
+std::string fs_ext (std::string path);
+std::string fs_path (std::string path);
+std::string fs_replace_extension(std::string path, std::string ext);
+
+#endif // _FILE_MANIP_H_
diff --git a/clocl/main.cpp b/clocl/main.cpp
new file mode 100644
index 0000000..05f0925
--- /dev/null
+++ b/clocl/main.cpp
@@ -0,0 +1,396 @@
+/******************************************************************************
+ * Copyright (c) 2013-2014, Texas Instruments Incorporated - http://www.ti.com/
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Texas Instruments Incorporated nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+#include <iostream>
+#include <iomanip>
+#include <string>
+#include <fstream>
+#include <sstream>
+#include <cstdlib>
+#include <sys/stat.h>
+
+#include <llvm/Bitcode/ReaderWriter.h>
+#include <llvm/PassManager.h>
+#include <llvm/Analysis/Passes.h>
+#include <llvm/Analysis/Verifier.h>
+#include <llvm/Transforms/Scalar.h>
+#include <llvm/Transforms/IPO.h>
+#include <llvm/Transforms/Utils/UnifyFunctionExitNodes.h>
+#include <llvm/Support/raw_ostream.h>
+#include <llvm/ADT/StringRef.h>
+#include <llvm/ADT/SmallVector.h>
+#include <llvm/Support/MemoryBuffer.h>
+#include <llvm/Support/Casting.h>
+#include <llvm/Bitcode/ReaderWriter.h>
+#include <llvm/IR/LLVMContext.h>
+#include <llvm/IR/Module.h>
+#include <llvm/Linker.h>
+#include <llvm/IR/Metadata.h>
+#include <llvm/IR/Function.h>
+#include <llvm/IR/Instructions.h>
+#include <llvm/Support/InstIterator.h>
+
+#include "compiler.h"
+#include "wga.h"
+#include "file_manip.h"
+#include "options.h"
+
+#include <WorkitemHandlerChooser.h>
+#include <BreakConstantGEPs.h>
+#include <Flatten.h>
+#include <PHIsToAllocas.h>
+#include <IsolateRegions.h>
+#include <VariableUniformityAnalysis.h>
+#include <ImplicitLoopBarriers.h>
+#include <LoopBarriers.h>
+#include <BarrierTailReplication.h>
+#include <CanonicalizeBarriers.h>
+#include <WorkItemAliasAnalysis.h>
+#include <WorkitemReplication.h>
+#include <WorkitemLoops.h>
+#include <AllocasToEntry.h>
+#include <Workgroup.h>
+#include <TargetAddressSpaces.h>
+
+using namespace std;
+using llvm::Module;
+
+bool prepend_headers(string filename, string& source);
+bool run_clang (string filename, string source, Compiler &compiler,
+ Module **module, string& binary);
+bool llvm_xforms (Module *module, bool optimize);
+bool cl6x (string& filename, string &binary_str);
+
+int run_cl6x (string filename, string *llvm_bitcode, string options);
+void write_binary (string filename, const char *buf, int size);
+void write_text (string filename);
+
+
+void write_bitcode(string filename, Module* module)
+{
+ string bc_file(fs_filename(fs_replace_extension(filename, ".bc")));
+ string err_info;
+
+ llvm::raw_fd_ostream file_ostream(bc_file.c_str(), err_info);
+ llvm::WriteBitcodeToFile(module, file_ostream);
+ file_ostream.flush();
+}
+
+/******************************************************************************
+* main
+******************************************************************************/
+int main(int argc, char *argv[])
+{
+ process_options(argc, argv);
+
+ if (files_clc.empty()) return 0;
+
+ string filename = files_clc[0];
+ string source; // OpenCL C program source
+ string binary; // Untransformed LLVM bitcode (still per workitem)
+ Module *module; // module, evolves during transformation
+ Compiler compiler;
+
+ if (!prepend_headers(filename, source)) exit(-1);
+ if (!run_clang (filename, source, compiler, &module, binary)) exit(-1);
+ if (!llvm_xforms (module, compiler.optimize())) exit(-1);
+
+ write_bitcode(filename, module);
+
+ if (!cl6x (filename, binary)) exit(-1);
+
+ if (opt_txt) write_text(filename);
+}
+
+
+
+/******************************************************************************
+* prepend_headers
+******************************************************************************/
+bool prepend_headers(string filename, string& source)
+{
+ /*---------------------------------------------------------------------
+ * Compile the Kernel Source for the device
+ *--------------------------------------------------------------------*/
+ if (!fs_exists(filename))
+ { cout << "File " << filename << " doesn't exist" << endl; return false; }
+
+ stringstream userSrc;
+ userSrc << ifstream(filename.c_str()).rdbuf();
+
+ /*-------------------------------------------------------------------------
+ * Prepend OpenCL header info into the source
+ *------------------------------------------------------------------------*/
+ source = userSrc.str();
+ return true;
+}
+
+/******************************************************************************
+* run_clang
+******************************************************************************/
+bool run_clang(string filename, string source, Compiler &compiler,
+ Module **module, string& binary)
+{
+ using llvm::MemoryBuffer;
+ using llvm::StringRef;
+
+ const StringRef s_data(source);
+ const StringRef s_name("<source>");
+
+ MemoryBuffer *buffer = MemoryBuffer::getMemBuffer(s_data, s_name);
+
+ if (opt_verbose) cout << "clang options: " << cl_options << endl;
+ if (!compiler.compile(cl_options, buffer, filename))
+ return false;
+
+ *module = compiler.module();
+
+ llvm::raw_string_ostream str_ostream(binary);
+ llvm::WriteBitcodeToFile(*module, str_ostream);
+ str_ostream.flush();
+
+ return true;
+}
+
+/******************************************************************************
+* llvm_xforms
+******************************************************************************/
+bool llvm_xforms(Module *module, bool optimize)
+{
+ // Get list of kernels to strip other unused functions
+ vector<const char *> api;
+ vector<string> api_s; // Needed to keep valid data in api
+
+ llvm::NamedMDNode *kern_meta = module->getNamedMetadata("opencl.kernels");
+
+ for (unsigned int i=0; kern_meta && i < kern_meta->getNumOperands(); ++i)
+ {
+ llvm::MDNode *node = kern_meta->getOperand(i);
+ llvm::Value *value = node->getOperand(0);
+ if (!llvm::isa<llvm::Function>(value)) continue;
+
+ llvm::Function *f = llvm::cast<llvm::Function>(value);
+ string s = f->getName().str();
+ api_s.push_back(s);
+ api.push_back(s.c_str());
+ }
+
+ // determine if module has barrier() function calls
+ bool hasBarrier = false;
+ llvm::CallInst* call;
+ for (Module::iterator F = module->begin(),
+ EF = module->end(); !hasBarrier && F != EF; ++F)
+ for (llvm::inst_iterator I = inst_begin(*F),
+ E = inst_end(*F); I != E; ++I)
+ {
+ if (!(call = llvm::dyn_cast<llvm::CallInst>(&*I))) continue;
+ if (!call->getCalledFunction()) continue;
+ string name(call->getCalledFunction()->getName());
+ if (name == "barrier")
+ {
+ hasBarrier = true;
+ break;
+ }
+ }
+
+ // Optimize code
+ llvm::PassManager *manager = new llvm::PassManager();
+
+ // Common passes (primary goal : remove unused stdlib functions)
+ manager->add(llvm::createTypeBasedAliasAnalysisPass());
+ manager->add(llvm::createBasicAliasAnalysisPass());
+
+ /*-------------------------------------------------------------------------
+ * Do not run this for lib mode as it will result in all functions
+ * being removed if main not found.
+ *------------------------------------------------------------------------*/
+ if (!opt_lib) manager->add(llvm::createInternalizePass(api));
+
+ manager->add(llvm::createIPSCCPPass());
+ manager->add(llvm::createGlobalOptimizerPass());
+ manager->add(llvm::createConstantMergePass());
+ manager->add(llvm::createAlwaysInlinerPass());
+
+ // pocl barrier transformation
+ if (hasBarrier)
+ {
+ manager->add(new llvm::DominatorTree());
+ manager->add(new pocl::WorkitemHandlerChooser());
+ manager->add(new BreakConstantGEPs()); // from pocl
+ // add(new GenerateHeader()); // no need
+ manager->add(new pocl::Flatten());
+ manager->add( llvm::createAlwaysInlinerPass());
+ manager->add( llvm::createGlobalDCEPass());
+ manager->add( llvm::createCFGSimplificationPass());
+ manager->add( llvm::createLoopSimplifyPass());
+ manager->add(new pocl::PHIsToAllocas());
+ manager->add( llvm::createRegionInfoPass());
+ manager->add(new pocl::IsolateRegions());
+ manager->add(new pocl::VariableUniformityAnalysis()); // TODO
+ manager->add(new pocl::ImplicitLoopBarriers());
+ manager->add(new pocl::LoopBarriers());
+ manager->add(new pocl::BarrierTailReplication());
+ manager->add(new pocl::CanonicalizeBarriers());
+ manager->add(new pocl::IsolateRegions());
+ manager->add(new pocl::WorkItemAliasAnalysis());
+ // add(new pocl::WorkitemReplication()); // no need
+ manager->add(new pocl::WorkitemLoops());
+ manager->add(new pocl::AllocasToEntry());
+ // add(new pocl::Workgroup()); // no need
+ manager->add(new pocl::TargetAddressSpaces());
+ }
+
+ if (optimize)
+ {
+ /*---------------------------------------------------------------------
+ * Inspired by code from "The LLVM Compiler Infrastructure"
+ *--------------------------------------------------------------------*/
+ manager->add(llvm::createDeadArgEliminationPass());
+ manager->add(llvm::createInstructionCombiningPass());
+ manager->add(llvm::createFunctionInliningPass());
+ manager->add(llvm::createPruneEHPass()); // Remove dead EH info.
+ manager->add(llvm::createGlobalOptimizerPass());
+ manager->add(llvm::createGlobalDCEPass()); // Remove dead functions.
+ manager->add(llvm::createArgumentPromotionPass());
+ manager->add(llvm::createInstructionCombiningPass());
+ manager->add(llvm::createJumpThreadingPass());
+
+ //ASW TODO maybe turn off re: pete. might gen bad xlator input
+ //manager->add(llvm::createScalarReplAggregatesPass());
+
+ manager->add(llvm::createFunctionAttrsPass()); // Add nocapture.
+ manager->add(llvm::createGlobalsModRefPass()); // IP alias analysis.
+ manager->add(llvm::createLICMPass()); // Hoist loop invariants.
+ manager->add(llvm::createGVNPass()); // Remove redundancies.
+ manager->add(llvm::createMemCpyOptPass()); // Remove dead memcpys.
+ manager->add(llvm::createDeadStoreEliminationPass());
+ manager->add(llvm::createInstructionCombiningPass());
+ manager->add(llvm::createJumpThreadingPass());
+ manager->add(llvm::createCFGSimplificationPass());
+ }
+
+ /*-------------------------------------------------------------------------
+ * Builtins will not have workitem functions and do not need wga
+ *------------------------------------------------------------------------*/
+ if (!opt_builtin)
+ {
+ manager->add(llvm::createUnifyFunctionExitNodesPass());
+ manager->add(llvm::createTIOpenclWorkGroupAggregationPass(hasBarrier));
+
+ /*---------------------------------------------------------------------
+ * Borrow the pocl alloca hoister for the TI simplistic WGA pass as well
+ *--------------------------------------------------------------------*/
+ if (!hasBarrier)
+ manager->add(new pocl::AllocasToEntry());
+ }
+
+ manager->add(llvm::createGlobalDCEPass());
+ manager->run(*module);
+ delete manager;
+
+ return true;
+}
+
+
+/******************************************************************************
+* cl6x
+******************************************************************************/
+bool cl6x(string& filename, string &binary_str)
+{
+ string bc_file_full(fs_replace_extension(filename, ".bc"));
+ string bc_file (fs_filename(bc_file_full));
+
+ run_cl6x(bc_file, &binary_str, files_other);
+
+ /*-------------------------------------------------------------------------
+ * Clean up temporary files
+ *------------------------------------------------------------------------*/
+ struct stat statbuf;
+ if (!opt_keep)
+ {
+ const char *name = bc_file_full.c_str();
+
+ unlink(name);
+
+ if (!opt_lib)
+ {
+ name = fs_replace_extension(bc_file_full, ".obj").c_str();
+ unlink(name);
+ }
+
+ string bitasm_name(fs_stem(bc_file_full));
+ bitasm_name += "_bc.asm";
+ name = bitasm_name.c_str();
+
+ unlink(name);
+
+ bitasm_name =fs_stem(bc_file_full);
+ bitasm_name += "_bc.obj";
+ name = bitasm_name.c_str();
+
+ unlink(name);
+ }
+
+ return true;
+}
+
+/******************************************************************************
+* write_text
+******************************************************************************/
+void write_text(string filename)
+{
+ filename = fs_filename(filename);
+ string outfile(fs_replace_extension(filename, ".out"));
+ string hfile (fs_replace_extension(filename, ".dsp_h"));
+
+ stringstream bufss;
+ bufss << ifstream(outfile.c_str()).rdbuf();
+
+ string buf(bufss.str());
+
+ ofstream header(hfile.c_str(), ios::out);
+
+ header << "unsigned int " << fs_stem(filename)
+ << "_dsp_bin_len = " << buf.length() << ";"
+ << endl;
+
+ header << "char " << fs_stem(filename) << "_dsp_bin[] = { ";
+
+ int val = buf[0] & 0xff;
+ header << "0x"<< hex << setfill('0') << setw(2) << nouppercase <<val<<endl;
+
+ for (int i = 1; i < buf.length(); i++)
+ {
+ val = buf[i] & 0xff;
+ header << ", 0x"<< hex << setfill('0') << setw(2) << nouppercase <<val;
+ if (i % 13 == 0) header << endl;
+ }
+
+ header << endl << "};" << endl;
+ header.close();
+}
+
diff --git a/clocl/options.cpp b/clocl/options.cpp
new file mode 100644
index 0000000..a6d9a87
--- /dev/null
+++ b/clocl/options.cpp
@@ -0,0 +1,223 @@
+#include <stdio.h> /* for printf */
+#include <stdlib.h> /* for exit */
+#include <getopt.h>
+
+#include <string>
+#include <vector>
+#include <iostream>
+#include <iterator>
+#include <algorithm>
+
+#include "file_manip.h"
+
+using std::cout;
+using std::endl;
+using std::string;
+using std::vector;
+using std::ostream_iterator;
+
+int opt_help = 0;
+int opt_verbose = 0;
+int opt_keep = 0;
+int opt_debug = 0;
+int opt_lib = 0;
+int opt_txt = 0;
+int opt_w = 0;
+int opt_Werror = 0;
+int opt_builtin = 0;
+
+string cl_options;
+string cl_incdef;
+string opts_other;
+vector<string> files_clc;
+vector<string> files_c;
+string files_other;
+
+/******************************************************************************
+* void print_options()
+******************************************************************************/
+void print_options()
+{
+ cout << endl;
+
+ if (opt_keep) printf ("Option keep : on\n");
+ if (opt_debug) printf ("Option debug : on\n");
+ if (opt_lib) printf ("Option lib : on\n");
+ if (opt_txt) printf ("Option txt : on\n");
+ if (opt_w) printf ("Option w : on\n");
+ if (opt_Werror) printf ("Option Werror : on\n");
+ //if (opt_builtin) printf ("Option builtin: on\n");
+
+ cout << endl;
+
+ cout << "CL C Options : " << cl_options << endl;
+ cout << "Incls/Defines : " << cl_incdef << endl;
+ cout << "CL C file : " << files_clc[0] << endl;
+ cout << "Link Files : " << files_other << endl;
+
+ cout << endl;
+
+ cout << "Ignored Opts : " << opts_other << endl;
+ cout << "Ignored Files : ";
+ if (files_clc.size() > 1)
+ copy(files_clc.begin()+1, files_clc.end(), ostream_iterator<string>(cout, " "));
+
+ copy(files_c.begin(), files_c.end(), ostream_iterator<string>(cout, " "));
+ cout << endl << endl;
+}
+
+/******************************************************************************
+* void print_help()
+******************************************************************************/
+void print_help()
+{
+ cout << endl;
+ cout << "Usage: clocl [options] <OpenCL C file> [<link files>]" << endl;
+ cout << endl;
+
+ cout << "Options passed to clocl are either options to control" << endl;
+ cout << "clocl behavior or they are documented OpenCL 1.1 build" << endl;
+ cout << "options." << endl;
+ cout << endl;
+ cout << "The clocl behavior options are: " << endl;
+ cout << " -h, --help : Print this help screen" << endl;
+ cout << " -v, --verbose : Print verbose messages" << endl;
+ cout << " -k, --keep : Do not delete temp compilation files" << endl;
+ cout << " -g, --debug : Generate debug symbols" << endl;
+ cout << " -t, --txt : Generate object in header form" << endl;
+ cout << " -l, --lib : Do not link. Stop after compilation." << endl;
+ cout << endl;
+ cout << "The OpenCL 1.1 build options. Refer to 1.1 spec for desc:" << endl;
+ cout << " -D<name>" << endl;
+ cout << " -D<name>=<val>" << endl;
+ cout << " -I<dir>" << endl;
+ cout << " -w" << endl;
+ cout << " -Werror" << endl;
+ cout << " -cl-single-precision-constant" << endl;
+ cout << " -cl-denorms-are-zero" << endl;
+ cout << " -cl-opt-disable" << endl;
+ cout << " -cl-mad-enable" << endl;
+ cout << " -cl-no-signed-zeros" << endl;
+ cout << " -cl-unsafe-math-optimizations" << endl;
+ cout << " -cl-finite-math-only" << endl;
+ cout << " -cl-fast-relaxed-math" << endl;
+ cout << " -cl-std=<val>" << endl;
+ cout << endl;
+ exit(-1);
+}
+
+/******************************************************************************
+* void process_options(int argc, char **argv)
+******************************************************************************/
+void process_options(int argc, char **argv)
+{
+ int c;
+ int digit_optind = 0;
+
+ while (1)
+ {
+ static struct option long_options[] = {
+
+ /*-----------------------------------------------------------------
+ * clocl options
+ *----------------------------------------------------------------*/
+ {"help", no_argument, &opt_help, 'h' },
+ {"verbose", no_argument, &opt_verbose, 'v' },
+ {"keep", no_argument, &opt_keep, 'k' },
+ {"debug", no_argument, &opt_debug, 'g' },
+ {"lib", no_argument, &opt_lib, 'l' },
+ {"txt", no_argument, &opt_txt, 't' },
+ {"builtin", no_argument, &opt_builtin, 'b' },
+
+ /*-----------------------------------------------------------------
+ * opencl 1.1 options
+ *----------------------------------------------------------------*/
+ {"Werror", no_argument, 0, 0 },
+ {"cl-std", required_argument, 0, 0 },
+ {"cl-single-precision-constant", no_argument, 0, 0 },
+ {"cl-denorms-are-zero", no_argument, 0, 0 },
+ {"cl-opt-disable", no_argument, 0, 0 },
+ {"cl-mad-enable", no_argument, 0, 0 },
+ {"cl-no-signed-zeros", no_argument, 0, 0 },
+ {"cl-unsafe-math-optimizations", no_argument, 0, 0 },
+ {"cl-finite-math-only", no_argument, 0, 0 },
+ {"cl-fast-relaxed-math", no_argument, 0, 0 },
+ {0, 0, 0, 0 }
+ };
+
+ int this_option_optind = optind ? optind : 1;
+ int option_index = 0;
+
+ opterr = 0; // prevent getopt from printing warnings
+
+ c = getopt_long_only(argc, argv, "-gwI:D:", long_options,
+ &option_index);
+ if (c == -1) break;
+
+ switch (c)
+ {
+ case 0:
+ {
+ string name(long_options[option_index].name);
+
+ if (name == "help" || name == "verbose" ||
+ name == "keep" || name == "debug" ||
+ name == "lib" || name == "txt" ||
+ name == "builtin") break;
+
+ if (name == "cl-std")
+ {
+ cl_options += " -cl-std=";
+ cl_options += optarg;
+ break;
+ }
+
+ if (name == "Werror") opt_Werror = 1; // fall-through
+ if (name == "cl-opt-disable") opt_debug = 1; // fall-through
+
+ cl_options += " ";
+ cl_options += argv[this_option_optind];
+ break;
+ }
+
+ case 1:
+ {
+ string fname(argv[this_option_optind]);
+ string ext(fs_ext(fname));
+
+ if (ext == ".clc") files_clc.push_back(fname);
+ else if (ext == ".cl") files_clc.push_back(fname);
+ else if (ext == ".c") files_c.push_back(fname);
+ else { files_other += fname; files_other += " "; }
+
+ break;
+ }
+
+ case 'g': opt_debug = 1; break;
+ case 'w': opt_w = 1; cl_options += " -w"; break;
+
+ case 'D':
+ case 'I':
+ cl_incdef += " -";
+ cl_incdef += c;
+ cl_incdef += optarg;
+ break;
+
+ case '?':
+ opts_other += " ";
+ opts_other += argv[this_option_optind];
+ break;
+
+ default:
+ opts_other += " -";
+ opts_other += c;
+ break;
+ }
+ }
+
+ if (opt_verbose) print_options();
+ if (opt_help) print_help();
+
+ cl_options += " ";
+ cl_options += cl_incdef;
+}
diff --git a/clocl/options.h b/clocl/options.h
new file mode 100644
index 0000000..086e49c
--- /dev/null
+++ b/clocl/options.h
@@ -0,0 +1,24 @@
+#ifndef _OPTIONS_H_
+#define _OPTIONS_H_
+
+#include <string>
+
+extern int opt_help;
+extern int opt_verbose;
+extern int opt_keep;
+extern int opt_debug;
+extern int opt_lib;
+extern int opt_txt;
+extern int opt_w;
+extern int opt_Werror;
+extern int opt_builtin;
+
+extern std::string cl_options;
+extern std::string cl_incdef;
+extern std::vector<std::string> files_clc;
+extern std::vector<std::string> files_c;
+extern std::string files_other;
+
+void process_options(int argc, char **argv);
+
+#endif //_OPTIONS_H_
diff --git a/clocl/program.cpp b/clocl/program.cpp
new file mode 100644
index 0000000..0674bbe
--- /dev/null
+++ b/clocl/program.cpp
@@ -0,0 +1,189 @@
+/******************************************************************************
+ * Copyright (c) 2013-2014, Texas Instruments Incorporated - http://www.ti.com/
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Texas Instruments Incorporated nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************************/
+#include <llvm/PassManager.h>
+#include <llvm/Analysis/Passes.h>
+#include <llvm/Analysis/Verifier.h>
+#include <llvm/Transforms/Scalar.h>
+#include <llvm/Transforms/IPO.h>
+#include <llvm/Transforms/Utils/UnifyFunctionExitNodes.h>
+#include <llvm/Support/raw_ostream.h>
+#include <llvm/Bitcode/ReaderWriter.h>
+#include "wga.h"
+#include "file_manip.h"
+#include "options.h"
+
+#include <string>
+#include <iostream>
+#include <fstream>
+#include <sstream>
+#include <stdio.h>
+#include <stdlib.h>
+#include <vector>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/wait.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include <elf.h>
+
+using namespace std;
+
+/******************************************************************************
+* Find the C6000 CGT installation
+******************************************************************************/
+char *get_cgt_install()
+{
+ char *install = getenv("TI_OCL_CGT_INSTALL");
+ if (!install)
+ {
+ std::cout <<
+ "The environment variable TI_OCL_CGT_INSTALL must be set to a "
+ << std::endl <<
+ "directory path where the C6000 compiler tools are installed. "
+ << std::endl;
+
+ abort();
+ }
+
+ return install;
+}
+
+/******************************************************************************
+* Find the OpenCL installation
+******************************************************************************/
+char *get_ocl_install()
+{
+ char *install = getenv("TI_OCL_INSTALL");
+ if (!install)
+ {
+ std::cout <<
+ "The environment variable TI_OCL_INSTALL must be set to a "
+ << std::endl <<
+ "directory path where the TI OpenCL product is installed. "
+ << std::endl;
+
+ abort();
+ }
+
+ return install;
+}
+
+std::string get_ocl_dsp()
+{
+ const char *stdpath = "/usr/share/ti/opencl/dsp";
+
+ struct stat st;
+ stat(stdpath, &st);
+ if (S_ISDIR(st.st_mode)) return stdpath;
+
+ std::string sinstall = string(get_ocl_install()) + "/dsp";
+ return sinstall;
+}
+
+/******************************************************************************
+* run_cl6x
+******************************************************************************/
+int run_cl6x(string filename, string *llvm_bitcode, string addl_files)
+{
+ string command("cl6x --f -q --abi=eabi --use_g3 -mv6600 -mt -mo ");
+
+ if (opt_keep) command += "-mw -k --z ";
+
+ command += "--disable:sploop ";
+
+ if (opt_debug) command += "-g -o0 ";
+ else command += "-o3 ";
+
+ const char *cgt_install = get_cgt_install();
+
+ command += "-I"; command += cgt_install; command += "/include ";
+ command += "-I"; command += cgt_install; command += "/lib ";
+ command += "-I"; command += get_ocl_dsp().c_str(); command += " ";
+
+ command += "--bc_file="; command += filename; command += " ";
+
+ /*-------------------------------------------------------------------------
+ * Encode LLVM bitcode as bytes in the .llvmir section of the .asm file
+ *------------------------------------------------------------------------*/
+ if (llvm_bitcode != NULL)
+ {
+ string bitasm_name(fs_stem(filename));
+ bitasm_name += "_bc.asm";
+
+ ofstream outasmfile(bitasm_name.c_str(), ios::out);
+ outasmfile << "\t.sect \".llvmir\"\n" << "\t.retain";
+ int nbytes = llvm_bitcode->size();
+ for (int i = 0; i < nbytes; i++)
+ if (i % 10 == 0)
+ outasmfile << "\n\t.byte " << (int) llvm_bitcode->at(i);
+ else
+ outasmfile << ", " << (int) llvm_bitcode->at(i);
+ outasmfile.close();
+
+ command += bitasm_name; command += " ";
+ }
+
+ if (opt_lib)
+ {
+ if (opt_verbose) cout << command << endl;
+ int x = system(command.c_str());
+ return true;
+ }
+
+ string outfile(fs_replace_extension(filename, ".out"));
+
+ command += "-z ";
+ command += "-o ";
+ command += outfile;
+ command += " ";
+
+ if (opt_keep)
+ {
+ command += "-m ";
+ command += fs_replace_extension(filename, ".map");
+ command += " ";
+ }
+
+ /*-------------------------------------------------------------------------
+ * Any libraries or object files need to go last to resolve references
+ *------------------------------------------------------------------------*/
+ command += addl_files;
+ command += " -ldsp.syms ";
+
+ if (opt_verbose) cout << command << endl;
+ int x = system(command.c_str());
+
+ if (!opt_debug)
+ {
+ string strip_command("strip6x ");
+ strip_command += outfile;
+ if (opt_verbose) cout << strip_command << endl;
+ x = system(strip_command.c_str());
+ }
+}