Clover Git
OpenCL 1.1 software implementation

compiler.cpp

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2011, Denis Steckelmacher <steckdenis@yahoo.fr>
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions are met:
00007  *     * Redistributions of source code must retain the above copyright
00008  *       notice, this list of conditions and the following disclaimer.
00009  *     * Redistributions in binary form must reproduce the above copyright
00010  *       notice, this list of conditions and the following disclaimer in the
00011  *       documentation and/or other materials provided with the distribution.
00012  *     * Neither the name of the copyright holder nor the
00013  *       names of its contributors may be used to endorse or promote products
00014  *       derived from this software without specific prior written permission.
00015  *
00016  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
00017  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00018  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00019  * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
00020  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00021  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00022  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00023  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00024  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00025  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00026  */
00027 
00033 #include "compiler.h"
00034 
00035 #include <cstring>
00036 #include <string>
00037 #include <sstream>
00038 #include <iostream>
00039 #include <clang/Frontend/CompilerInvocation.h>
00040 #include <clang/Frontend/TextDiagnosticPrinter.h>
00041 #include <clang/Frontend/LangStandard.h>
00042 #include <clang/Basic/Diagnostic.h>
00043 #include <clang/CodeGen/CodeGenAction.h>
00044 #include <llvm/ADT/SmallVector.h>
00045 #include <llvm/Support/Host.h>
00046 #include <llvm/Module.h>
00047 #include <llvm/LLVMContext.h>
00048 
00049 using namespace Coal;
00050 
00051 Compiler::Compiler(DeviceInterface *device)
00052 : p_device(device), p_module(0), p_optimize(true), p_log_stream(p_log),
00053   p_log_printer(0)
00054 {
00055 
00056 }
00057 
00058 Compiler::~Compiler()
00059 {
00060 
00061 }
00062 
00063 bool Compiler::compile(const std::string &options,
00064                                 llvm::MemoryBuffer *source)
00065 {
00066     /* Set options */
00067     p_options = options;
00068 
00069     clang::CodeGenOptions &codegen_opts = p_compiler.getCodeGenOpts();
00070     clang::DiagnosticOptions &diag_opts = p_compiler.getDiagnosticOpts();
00071     clang::FrontendOptions &frontend_opts = p_compiler.getFrontendOpts();
00072     clang::HeaderSearchOptions &header_opts = p_compiler.getHeaderSearchOpts();
00073     clang::LangOptions &lang_opts = p_compiler.getLangOpts();
00074     clang::TargetOptions &target_opts = p_compiler.getTargetOpts();
00075     clang::PreprocessorOptions &prep_opts = p_compiler.getPreprocessorOpts();
00076     clang::CompilerInvocation &invocation = p_compiler.getInvocation();
00077 
00078     // Set codegen options
00079     codegen_opts.DebugInfo = false;
00080     codegen_opts.AsmVerbose = true;
00081     codegen_opts.OptimizationLevel = 3;
00082 
00083     // Set diagnostic options
00084     diag_opts.Pedantic = true;
00085     diag_opts.ShowColumn = true;
00086     diag_opts.ShowLocation = true;
00087     diag_opts.ShowCarets = false;
00088     diag_opts.ShowFixits = true;
00089     diag_opts.ShowColors = false;
00090     diag_opts.ErrorLimit = 19;
00091     diag_opts.MessageLength = 0;
00092 
00093     // Set frontend options
00094     frontend_opts.ProgramAction = clang::frontend::EmitLLVMOnly;
00095     frontend_opts.DisableFree = true;
00096 
00097     // Set header search options
00098     header_opts.Verbose = false;
00099     header_opts.UseBuiltinIncludes = false;
00100     header_opts.UseStandardIncludes = false;
00101     header_opts.UseStandardCXXIncludes = false;
00102 
00103     // Set preprocessor options
00104     prep_opts.RetainRemappedFileBuffers = true;
00105 
00106     // Set lang options
00107     lang_opts.NoBuiltin = true;
00108     lang_opts.OpenCL = true;
00109 
00110     // Set target options
00111     target_opts.Triple = llvm::sys::getHostTriple();
00112 
00113     // Set invocation options
00114     invocation.setLangDefaults(clang::IK_OpenCL);
00115 
00116     // Parse the user options
00117     std::istringstream options_stream(options);
00118     std::string token;
00119     bool Werror = false, inI = false, inD = false;
00120 
00121     while (options_stream >> token)
00122     {
00123         if (inI)
00124         {
00125             // token is an include path
00126             header_opts.AddPath(token, clang::frontend::Angled, true, false, false);
00127             inI = false;
00128             continue;
00129         }
00130         else if (inD)
00131         {
00132             // token is name or name=value
00133             prep_opts.addMacroDef(token);
00134         }
00135 
00136         if (token == "-I")
00137         {
00138             inI = true;
00139         }
00140         else if (token == "-D")
00141         {
00142             inD = true;
00143         }
00144         else if (token == "-cl-single-precision-constant")
00145         {
00146             lang_opts.SinglePrecisionConstants = true;
00147         }
00148         else if (token == "-cl-opt-disable")
00149         {
00150             p_optimize = false;
00151             codegen_opts.OptimizationLevel = 0;
00152         }
00153         else if (token == "-cl-mad-enable")
00154         {
00155             codegen_opts.LessPreciseFPMAD = true;
00156         }
00157         else if (token == "-cl-unsafe-math-optimizations")
00158         {
00159             codegen_opts.UnsafeFPMath = true;
00160         }
00161         else if (token == "-cl-finite-math-only")
00162         {
00163             codegen_opts.NoInfsFPMath = true;
00164             codegen_opts.NoNaNsFPMath = true;
00165         }
00166         else if (token == "-cl-fast-relaxed-math")
00167         {
00168             codegen_opts.UnsafeFPMath = true;
00169             codegen_opts.NoInfsFPMath = true;
00170             codegen_opts.NoNaNsFPMath = true;
00171             lang_opts.FastRelaxedMath = true;
00172         }
00173         else if (token == "-w")
00174         {
00175             diag_opts.IgnoreWarnings = true;
00176         }
00177         else if (token == "-Werror")
00178         {
00179             Werror = true;
00180         }
00181     }
00182 
00183     // Create the diagnostics engine
00184     p_log_printer = new clang::TextDiagnosticPrinter(p_log_stream, diag_opts);
00185     p_compiler.createDiagnostics(0, NULL, p_log_printer);
00186 
00187     if (!p_compiler.hasDiagnostics())
00188         return false;
00189 
00190     p_compiler.getDiagnostics().setWarningsAsErrors(Werror);
00191 
00192     // Feed the compiler with source
00193     frontend_opts.Inputs.push_back(std::make_pair(clang::IK_OpenCL, "program.cl"));
00194     prep_opts.addRemappedFile("program.cl", source);
00195 
00196     // Compile
00197     llvm::OwningPtr<clang::CodeGenAction> act(
00198         new clang::EmitLLVMOnlyAction(&llvm::getGlobalContext())
00199     );
00200 
00201     if (!p_compiler.ExecuteAction(*act))
00202     {
00203         // DEBUG
00204         std::cout << log() << std::endl;
00205         return false;
00206     }
00207 
00208     p_log_stream.flush();
00209     p_module = act->takeModule();
00210 
00211     // Cleanup
00212     prep_opts.eraseRemappedFile(prep_opts.remapped_file_buffer_end());
00213 
00214     return true;
00215 }
00216 
00217 const std::string &Compiler::log() const
00218 {
00219     return p_log;
00220 }
00221 
00222 const std::string &Compiler::options() const
00223 {
00224     return p_options;
00225 }
00226 
00227 bool Compiler::optimize() const
00228 {
00229     return p_optimize;
00230 }
00231 
00232 llvm::Module *Compiler::module() const
00233 {
00234     return p_module;
00235 }
00236 
00237 void Compiler::appendLog(const std::string &log)
00238 {
00239     p_log += log;
00240 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines