Clover Git
OpenCL 1.1 software implementation
|
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 }