1 // 2 // Copyright 2012-2016 Francisco Jerez 3 // Copyright 2012-2016 Advanced Micro Devices, Inc. 4 // 5 // Permission is hereby granted, free of charge, to any person obtaining a 6 // copy of this software and associated documentation files (the "Software"), 7 // to deal in the Software without restriction, including without limitation 8 // the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 // and/or sell copies of the Software, and to permit persons to whom the 10 // Software is furnished to do so, subject to the following conditions: 11 // 12 // The above copyright notice and this permission notice shall be included in 13 // all copies or substantial portions of the Software. 14 // 15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 19 // OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 20 // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 21 // OTHER DEALINGS IN THE SOFTWARE. 22 // 23 24 #ifndef CLOVER_LLVM_UTIL_HPP 25 #define CLOVER_LLVM_UTIL_HPP 26 27 #include "core/error.hpp" 28 #include "util/u_debug.h" 29 30 #include <vector> 31 #include <fstream> 32 #include <iostream> 33 #include <sstream> 34 35 namespace clover { 36 namespace llvm { 37 template<typename E> void fail(std::string & r_log,E && e,const std::string & s)38 fail(std::string &r_log, E &&e, const std::string &s) { 39 r_log += s; 40 throw e; 41 } 42 43 inline std::vector<std::string> tokenize(const std::string & s)44 tokenize(const std::string &s) { 45 std::vector<std::string> ss; 46 std::ostringstream oss; 47 48 // OpenCL programs can pass a quoted argument, most frequently the 49 // include path. This is useful so that path containing spaces is 50 // treated as a single argument instead of being split by the spaces. 51 // Additionally, the argument should also be unquoted before being 52 // passed to the compiler. We avoid using std::string::replace here to 53 // remove quotes, as the single and double quote characters can be a 54 // part of the file name. 55 bool escape_next = false; 56 bool in_quote_double = false; 57 bool in_quote_single = false; 58 59 for (auto c : s) { 60 if (escape_next) { 61 oss.put(c); 62 escape_next = false; 63 } else if (c == '\\') { 64 escape_next = true; 65 } else if (c == '"' && !in_quote_single) { 66 in_quote_double = !in_quote_double; 67 } else if (c == '\'' && !in_quote_double) { 68 in_quote_single = !in_quote_single; 69 } else if (c != ' ' || in_quote_single || in_quote_double) { 70 oss.put(c); 71 } else if (oss.tellp() > 0) { 72 ss.emplace_back(oss.str()); 73 oss.str(""); 74 } 75 } 76 77 if (oss.tellp() > 0) 78 ss.emplace_back(oss.str()); 79 80 if (in_quote_double || in_quote_single) 81 throw invalid_build_options_error(); 82 83 return ss; 84 } 85 86 inline std::string as_string(const std::vector<char> & v)87 as_string(const std::vector<char> &v) { 88 return { v.begin(), v.end() }; 89 } 90 91 struct target { targetclover::llvm::target92 target(const std::string &s) : 93 cpu(s.begin(), s.begin() + s.find_first_of("-")), 94 triple(s.begin() + s.find_first_of("-") + 1, s.end()) {} 95 96 std::string cpu; 97 std::string triple; 98 }; 99 100 namespace debug { 101 enum flag { 102 clc = 1 << 0, 103 llvm = 1 << 1, 104 native = 1 << 2 105 }; 106 107 inline bool has_flag(flag f)108 has_flag(flag f) { 109 static const struct debug_named_value debug_options[] = { 110 { "clc", clc, "Dump the OpenCL C code for all kernels." }, 111 { "llvm", llvm, "Dump the generated LLVM IR for all kernels." }, 112 { "native", native, "Dump kernel assembly code for targets " 113 "specifying PIPE_SHADER_IR_NATIVE" }, 114 DEBUG_NAMED_VALUE_END 115 }; 116 static const unsigned flags = 117 debug_get_flags_option("CLOVER_DEBUG", debug_options, 0); 118 119 return flags & f; 120 } 121 122 inline void log(const std::string & suffix,const std::string & s)123 log(const std::string &suffix, const std::string &s) { 124 const std::string path = debug_get_option("CLOVER_DEBUG_FILE", 125 "stderr"); 126 if (path == "stderr") 127 std::cerr << s; 128 else 129 std::ofstream(path + suffix, std::ios::app) << s; 130 } 131 } 132 } 133 } 134 135 #endif 136