clover: Fix build after llvm r332881.
[mesa.git] / src / gallium / state_trackers / clover / llvm / util.hpp
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
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>
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
87 as_string(const std::vector<char> &v) {
88 return { v.begin(), v.end() };
89 }
90
91 struct target {
92 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
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
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