• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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