1 //
2 // Copyright (c) 2017 The Khronos Group Inc.
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 // http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16 #include "parseParameters.h"
17
18 #include "errorHelpers.h"
19 #include "testHarness.h"
20 #include "ThreadPool.h"
21
22 #include <iostream>
23 #include <sstream>
24 #include <sys/types.h>
25 #include <sys/stat.h>
26 #include <string.h>
27
28 using namespace std;
29
30 #define DEFAULT_COMPILATION_PROGRAM "cl_offline_compiler"
31
32 CompilationMode gCompilationMode = kOnline;
33 CompilationCacheMode gCompilationCacheMode = kCacheModeCompileIfAbsent;
34 std::string gCompilationCachePath = ".";
35 std::string gCompilationProgram = DEFAULT_COMPILATION_PROGRAM;
36
helpInfo()37 void helpInfo()
38 {
39 log_info(
40 R"(Common options:
41 -h, --help
42 This help
43 --compilation-mode <mode>
44 Specify a compilation mode. Mode can be:
45 online Use online compilation (default)
46 binary Use binary offline compilation
47 spir-v Use SPIR-V offline compilation
48
49 For offline compilation (binary and spir-v modes) only:
50 --compilation-cache-mode <cache-mode>
51 Specify a compilation caching mode:
52 compile-if-absent
53 Read from cache if already populated, or else perform
54 offline compilation (default)
55 force-read
56 Force reading from the cache
57 overwrite
58 Disable reading from the cache
59 dump-cl-files
60 Dumps the .cl and build .options files used by the test suite
61 --compilation-cache-path <path>
62 Path for offline compiler output and CL source
63 --compilation-program <prog>
64 Program to use for offline compilation, defaults to:
65 )" DEFAULT_COMPILATION_PROGRAM "\n\n");
66 }
67
parseCustomParam(int argc,const char * argv[],const char * ignore)68 int parseCustomParam(int argc, const char *argv[], const char *ignore)
69 {
70 int delArg = 0;
71
72 for (int i = 1; i < argc; i++)
73 {
74 if (ignore != 0)
75 {
76 // skip parameters that require special/different treatment in
77 // application (generic interpretation and parameter removal will
78 // not be performed)
79 const char *ptr = strstr(ignore, argv[i]);
80 if (ptr != 0 && (ptr == ignore || ptr[-1] == ' ')
81 && // first on list or ' ' before
82 (ptr[strlen(argv[i])] == 0
83 || ptr[strlen(argv[i])] == ' ')) // last on list or ' ' after
84 continue;
85 }
86
87 delArg = 0;
88
89 if (strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "--help") == 0)
90 {
91 // Note: we don't increment delArg to delete this argument,
92 // to allow the caller's argument parsing routine to see the
93 // option and print its own help.
94 helpInfo();
95 }
96 else if (!strcmp(argv[i], "--compilation-mode"))
97 {
98 delArg++;
99 if ((i + 1) < argc)
100 {
101 delArg++;
102 const char *mode = argv[i + 1];
103
104 if (!strcmp(mode, "online"))
105 {
106 gCompilationMode = kOnline;
107 }
108 else if (!strcmp(mode, "binary"))
109 {
110 gCompilationMode = kBinary;
111 }
112 else if (!strcmp(mode, "spir-v"))
113 {
114 gCompilationMode = kSpir_v;
115 }
116 else
117 {
118 log_error("Compilation mode not recognized: %s\n", mode);
119 return -1;
120 }
121 log_info("Compilation mode specified: %s\n", mode);
122 }
123 else
124 {
125 log_error("Compilation mode parameters are incorrect. Usage:\n"
126 " --compilation-mode <online|binary|spir-v>\n");
127 return -1;
128 }
129 }
130 else if (!strcmp(argv[i], "--compilation-cache-mode"))
131 {
132 delArg++;
133 if ((i + 1) < argc)
134 {
135 delArg++;
136 const char *mode = argv[i + 1];
137
138 if (!strcmp(mode, "compile-if-absent"))
139 {
140 gCompilationCacheMode = kCacheModeCompileIfAbsent;
141 }
142 else if (!strcmp(mode, "force-read"))
143 {
144 gCompilationCacheMode = kCacheModeForceRead;
145 }
146 else if (!strcmp(mode, "overwrite"))
147 {
148 gCompilationCacheMode = kCacheModeOverwrite;
149 }
150 else if (!strcmp(mode, "dump-cl-files"))
151 {
152 gCompilationCacheMode = kCacheModeDumpCl;
153 }
154 else
155 {
156 log_error("Compilation cache mode not recognized: %s\n",
157 mode);
158 return -1;
159 }
160 log_info("Compilation cache mode specified: %s\n", mode);
161 }
162 else
163 {
164 log_error(
165 "Compilation cache mode parameters are incorrect. Usage:\n"
166 " --compilation-cache-mode "
167 "<compile-if-absent|force-read|overwrite>\n");
168 return -1;
169 }
170 }
171 else if (!strcmp(argv[i], "--compilation-cache-path"))
172 {
173 delArg++;
174 if ((i + 1) < argc)
175 {
176 delArg++;
177 gCompilationCachePath = argv[i + 1];
178 }
179 else
180 {
181 log_error("Path argument for --compilation-cache-path was not "
182 "specified.\n");
183 return -1;
184 }
185 }
186 else if (!strcmp(argv[i], "--compilation-program"))
187 {
188 delArg++;
189 if ((i + 1) < argc)
190 {
191 delArg++;
192 gCompilationProgram = argv[i + 1];
193 }
194 else
195 {
196 log_error("Program argument for --compilation-program was not "
197 "specified.\n");
198 return -1;
199 }
200 }
201
202 // cleaning parameters from argv tab
203 for (int j = i; j < argc - delArg; j++) argv[j] = argv[j + delArg];
204 argc -= delArg;
205 i -= delArg;
206 }
207
208 if ((gCompilationCacheMode == kCacheModeForceRead
209 || gCompilationCacheMode == kCacheModeOverwrite)
210 && gCompilationMode == kOnline)
211 {
212 log_error("Compilation cache mode can only be specified when using an "
213 "offline compilation mode.\n");
214 return -1;
215 }
216
217 return argc;
218 }
219
is_power_of_two(int number)220 bool is_power_of_two(int number) { return number && !(number & (number - 1)); }
221
parseWimpyReductionFactor(const char * & arg,int & wimpyReductionFactor)222 extern void parseWimpyReductionFactor(const char *&arg,
223 int &wimpyReductionFactor)
224 {
225 const char *arg_temp = strchr(&arg[1], ']');
226 if (arg_temp != 0)
227 {
228 int new_factor = atoi(&arg[1]);
229 arg = arg_temp; // Advance until ']'
230 if (is_power_of_two(new_factor))
231 {
232 log_info("\n Wimpy reduction factor changed from %d to %d \n",
233 wimpyReductionFactor, new_factor);
234 wimpyReductionFactor = new_factor;
235 }
236 else
237 {
238 log_info("\n WARNING: Incorrect wimpy reduction factor %d, must be "
239 "power of 2. The default value will be used.\n",
240 new_factor);
241 }
242 }
243 }
244