Intel SPMD Program Compiler  1.12.0
main.cpp
Go to the documentation of this file.
1 /*
2  Copyright (c) 2010-2019, Intel Corporation
3  All rights reserved.
4 
5  Redistribution and use in source and binary forms, with or without
6  modification, are permitted provided that the following conditions are
7  met:
8 
9  * Redistributions of source code must retain the above copyright
10  notice, this list of conditions and the following disclaimer.
11 
12  * Redistributions in binary form must reproduce the above copyright
13  notice, this list of conditions and the following disclaimer in the
14  documentation and/or other materials provided with the distribution.
15 
16  * Neither the name of Intel Corporation nor the names of its
17  contributors may be used to endorse or promote products derived from
18  this software without specific prior written permission.
19 
20 
21  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
22  IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23  TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
24  PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
25  OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
26  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
28  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
29  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
31  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33 
34 /** @file main.cpp
35  @brief main() entrypoint implementation for ispc
36 */
37 
38 #include "ispc.h"
39 #include "module.h"
40 #include "type.h"
41 #include "util.h"
42 #include <stdio.h>
43 #include <stdlib.h>
44 #ifdef ISPC_HOST_IS_WINDOWS
45 #include <time.h>
46 #else
47 #include <unistd.h>
48 #endif // ISPC_HOST_IS_WINDOWS
49 #include <llvm/Support/Debug.h>
50 #include <llvm/Support/Signals.h>
51 #include <llvm/Support/TargetRegistry.h>
52 #include <llvm/Support/TargetSelect.h>
53 
54 #ifdef ISPC_HOST_IS_WINDOWS
55 #define strcasecmp stricmp
56 #ifndef BUILD_DATE
57 #define BUILD_DATE __DATE__
58 #endif
59 #define BUILD_VERSION ""
60 #if _MSC_VER >= 1900
61 #define ISPC_VS_VERSION "Visual Studio 2015 and later"
62 #else
63 #define ISPC_VS_VERSION "Visual Studio 2013 and earlier"
64 #endif
65 #endif // ISPC_HOST_IS_WINDOWS
66 
67 #define MAX_NUM_ARGS (512)
68 
69 static void lPrintVersion() {
70 #ifdef ISPC_HOST_IS_WINDOWS
71  printf("Intel(r) SPMD Program Compiler (ispc), %s (build date %s, LLVM %s)\n"
72  "Supported Visual Studio versions: %s.\n",
73  ISPC_VERSION, BUILD_DATE, ISPC_LLVM_VERSION_STRING, ISPC_VS_VERSION);
74 #else
75  printf("Intel(r) SPMD Program Compiler (ispc), %s (build %s @ %s, LLVM %s)\n", ISPC_VERSION, BUILD_VERSION,
76  BUILD_DATE, ISPC_LLVM_VERSION_STRING);
77 #endif
78 
79 // The recommended way to build ISPC assumes custom LLVM build with a set of patches.
80 // If the default LLVM distribution is used, then the resuling ISPC binary may contain
81 // known and already fixed stability and performance problems.
82 #ifdef ISPC_NO_DUMPS
83  printf("This version is likely linked against non-recommended LLVM binaries.\n"
84  "For best stability and performance please use official binary distribution from "
85  "http://ispc.github.io/downloads.html");
86 #endif
87 }
88 
89 static void usage(int ret) {
90  lPrintVersion();
91  printf("\nusage: ispc\n");
92  printf(" [--addressing={32,64}]\t\tSelect 32- or 64-bit addressing. (Note that 32-bit\n");
93  printf(" \t\taddressing calculations are done by default, even\n");
94  printf(" \t\ton 64-bit target architectures.)\n");
95  printf(" [--arch={%s}]\t\tSelect target architecture\n", Target::SupportedArchs());
96  printf(" [--c++-include-file=<name>]\t\tSpecify name of file to emit in #include statement in generated C++ "
97  "code.\n");
98 #ifndef ISPC_HOST_IS_WINDOWS
99  printf(" [--colored-output]\t\tAlways use terminal colors in error/warning messages\n");
100 #endif
101  printf(" ");
102  char cpuHelp[2048];
103  snprintf(cpuHelp, sizeof(cpuHelp), "[--cpu=<cpu>]\t\t\tSelect target CPU type\n<cpu>={%s}\n",
104  Target::SupportedCPUs().c_str());
105  PrintWithWordBreaks(cpuHelp, 16, TerminalWidth(), stdout);
106  printf(" [-D<foo>]\t\t\t\t#define given value when running preprocessor\n");
107  printf(" [--dev-stub <filename>]\t\tEmit device-side offload stub functions to file\n");
108  printf(" [--dllexport]\t\t\tMake non-static functions DLL exported. Windows target only\n");
109 #if ISPC_LLVM_VERSION >= ISPC_LLVM_3_5
110  printf(" [--dwarf-version={2,3,4}]\t\tGenerate source-level debug information with given DWARF version "
111  "(triggers -g). Ignored for Windows target\n");
112 #endif
113  printf(" [--emit-asm]\t\t\tGenerate assembly language file as output\n");
114  printf(" [--x86-asm-syntax=<option>]\t\tSelect style of code if generating assembly\n");
115  printf(" intel\t\t\t\tEmit Intel-style assembly\n");
116  printf(" att\t\t\t\tEmit AT&T-style assembly\n");
117  printf(" [--emit-c++]\t\t\tEmit a C++ source file as output\n");
118  printf(" [--emit-llvm]\t\t\tEmit LLVM bitode file as output\n");
119  printf(" [--emit-llvm-text]\t\t\tEmit LLVM bitode file as output in textual form\n");
120  printf(" [--emit-obj]\t\t\tGenerate object file file as output (default)\n");
121  printf(" [--force-alignment=<value>]\t\tForce alignment in memory allocations routine to be <value>\n");
122  printf(" [-g]\t\t\t\tGenerate source-level debug information\n");
123  printf(" [--help]\t\t\t\tPrint help\n");
124  printf(" [--help-dev]\t\t\tPrint help for developer options\n");
125  printf(" [--host-stub <filename>]\t\tEmit host-side offload stub functions to file\n");
126  printf(" [-h <name>/--header-outfile=<name>]\tOutput filename for header\n");
127  printf(" [-I <path>]\t\t\t\tAdd <path> to #include file search path\n");
128  printf(" [--instrument]\t\t\tEmit instrumentation to gather performance data\n");
129  printf(" [--math-lib=<option>]\t\tSelect math library\n");
130  printf(" default\t\t\t\tUse ispc's built-in math functions\n");
131  printf(" fast\t\t\t\tUse high-performance but lower-accuracy math functions\n");
132  printf(" svml\t\t\t\tUse the Intel(r) SVML math libraries\n");
133  printf(" system\t\t\t\tUse the system's math library (*may be quite slow*)\n");
134  printf(" [-MMM <filename>]\t\t\tWrite #include dependencies to given file.\n");
135  printf(" [-M]\t\t\t\tOutput a rule suitable for `make' describing the dependencies of the main source file to "
136  "stdout.\n");
137  printf(" [-MF <filename>]\t\t\tWhen used with `-M', specifies a file to write the dependencies to.\n");
138  printf(" [-MT <filename>]\t\t\tWhen used with `-M', changes the target of the rule emitted by dependency "
139  "generation.\n");
140  printf(" [--no-omit-frame-pointer]\t\tDisable frame pointer omission. It may be useful for profiling\n");
141  printf(" [--nostdlib]\t\t\tDon't make the ispc standard library available\n");
142  printf(" [--no-pragma-once]\t\t\tDon't use #pragma once in created headers\n");
143  printf(" [--nocpp]\t\t\t\tDon't run the C preprocessor\n");
144  printf(" [-o <name>/--outfile=<name>]\tOutput filename (may be \"-\" for standard output)\n");
145  printf(" [-O0/-O(1/2/3)]\t\t\tSet optimization level. Default behavior is to optimize for speed.\n");
146  printf(" -O0\t\t\t\tOptimizations disabled.\n");
147  printf(" -O1\t\t\t\tOptimization for size.\n");
148  printf(" -O2/O3\t\t\t\tOptimization for speed.\n");
149  printf(" [--opt=<option>]\t\t\tSet optimization option\n");
150  printf(" disable-assertions\t\tRemove assertion statements from final code.\n");
151  printf(" disable-fma\t\t\tDisable 'fused multiply-add' instructions (on targets that support them)\n");
152  printf(" disable-loop-unroll\t\tDisable loop unrolling.\n");
153  printf(" fast-masked-vload\t\tFaster masked vector loads on SSE (may go past end of array)\n");
154  printf(" fast-math\t\t\tPerform non-IEEE-compliant optimizations of numeric expressions\n");
155  printf(" force-aligned-memory\t\tAlways issue \"aligned\" vector load and store instructions\n");
156  printf(" [--pic]\t\t\t\tGenerate position-independent code. Ignored for Windows target\n");
157  printf(" [--quiet]\t\t\t\tSuppress all output\n");
158  printf(" ");
159  char targetHelp[2048];
160  snprintf(targetHelp, sizeof(targetHelp),
161  "[--target=<t>]\t\t\tSelect target ISA and width.\n"
162  "<t>={%s}",
164  PrintWithWordBreaks(targetHelp, 24, TerminalWidth(), stdout);
165  printf(" ");
166  snprintf(targetHelp, sizeof(targetHelp), "[--target-os=<os>]\t\t\tSelect target OS. <os>={%s}",
168  PrintWithWordBreaks(targetHelp, 24, TerminalWidth(), stdout);
169  printf(" [--version]\t\t\t\tPrint ispc version\n");
170  printf(" [--werror]\t\t\t\tTreat warnings as errors\n");
171  printf(" [--woff]\t\t\t\tDisable warnings\n");
172  printf(" [--wno-perf]\t\t\tDon't issue warnings related to performance-related issues\n");
173  printf(" [@<filename>]\t\t\tRead additional arguments from the given file\n");
174  printf(" <file to compile or \"-\" for stdin>\n");
175  exit(ret);
176 }
177 
178 static void devUsage(int ret) {
179  lPrintVersion();
180  printf("\nusage (developer options): ispc\n");
181  printf(" [--debug]\t\t\t\tPrint information useful for debugging ispc\n");
182  printf(" [--debug-llvm]\t\t\tEnable LLVM debugging information (dumps to stderr)\n");
183  printf(" [--print-target]\t\t\tPrint target's information\n");
184  printf(" [--fuzz-test]\t\t\tRandomly perturb program input to test error conditions\n");
185  printf(" [--fuzz-seed=<value>]\t\tSeed value for RNG for fuzz testing\n");
186  printf(" [--opt=<option>]\t\t\tSet optimization option\n");
187  printf(" disable-all-on-optimizations\t\tDisable optimizations that take advantage of \"all on\" mask\n");
188  printf(" disable-blended-masked-stores\t\tScalarize masked stores on SSE (vs. using vblendps)\n");
189  printf(" disable-blending-removal\t\tDisable eliminating blend at same scope\n");
190  printf(" disable-coalescing\t\t\tDisable gather coalescing\n");
191  printf(" disable-coherent-control-flow\t\tDisable coherent control flow optimizations\n");
192  printf(" disable-gather-scatter-flattening\tDisable flattening when all lanes are on\n");
193  printf(" disable-gather-scatter-optimizations\tDisable improvements to gather/scatter\n");
194  printf(" disable-handle-pseudo-memory-ops\tLeave __pseudo_* calls for gather/scatter/etc. in final IR\n");
195  printf(" disable-uniform-control-flow\t\tDisable uniform control flow optimizations\n");
196  printf(" disable-uniform-memory-optimizations\tDisable uniform-based coherent memory access\n");
197  printf(" [--yydebug]\t\t\t\tPrint debugging information during parsing\n");
198 #ifndef ISPC_NO_DUMPS
199  printf(" [--debug-phase=<value>]\t\tSet optimization phases to dump. "
200  "--debug-phase=first,210:220,300,305,310:last\n");
201  printf(" [--dump-file]\t\t\tDump module IR to file(s) in current directory\n");
202 #endif
203 #if ISPC_LLVM_VERSION == ISPC_LLVM_3_4 || ISPC_LLVM_VERSION == ISPC_LLVM_3_5 // 3.4, 3.5
204  printf(" [--debug-ir=<value>]\t\tSet optimization phase to generate debugIR after it\n");
205 #endif
206  printf(" [--off-phase=<value>]\t\tSwitch off optimization phases. --off-phase=first,210:220,300,305,310:last\n");
207  exit(ret);
208 }
209 
210 /** Define an abstract base-class that implements the parsing of an character source and
211  * the breaking of it into the individual arguments
212  */
213 class ArgFactory {
214  private:
215  char *AllocateString(std::string string) {
216  int len = string.length();
217  char *ptr = new char[len + 1];
218  strncpy(ptr, string.c_str(), len);
219  ptr[len] = '\0';
220  return ptr;
221  }
222 
223  /** Method provided by the derived classes to retrieve the next character from the stream.
224  */
225  virtual char GetNextChar() = 0;
226 
227  public:
229 
230  char *GetNextArg() {
231  std::string arg;
232  char c = GetNextChar();
233 
234  // First consume any white-space before the argument
235  while (isspace(c))
236  c = GetNextChar();
237 
238  if (c == '\0')
239  // Reached the end so no more arguments
240  return NULL;
241 
242  // c now has the first character of the next argument, so collect the rest
243  while (c != '\0' && !isspace(c)) {
244  arg += c;
245  c = GetNextChar();
246  }
247 
248  return AllocateString(arg);
249  }
250 };
251 
252 /** Define a class to break the contents of an open file into the individual arguments */
253 class FileArgFactory : public ArgFactory {
254  private:
255  FILE *InputFile;
256 
257  virtual char GetNextChar() {
258  int c = fgetc(InputFile);
259  if (c == EOF) {
260  return '\0';
261  } else {
262  return c;
263  }
264  }
265 
266  public:
267  FileArgFactory(FILE *file) : InputFile(file) {}
268 };
269 
270 /** Define a class to break a NUL-terminated string into the individual arguments */
271 class StringArgFactory : public ArgFactory {
272  private:
273  const char *InputString;
274 
275  virtual char GetNextChar() {
276  char c = *InputString;
277 
278  if (c != '\0')
279  ++InputString;
280 
281  return c;
282  }
283 
284  public:
285  StringArgFactory(const char *string) : InputString(string) {}
286 };
287 
288 // Forward reference
289 static void lAddSingleArg(char *arg, int &argc, char *argv[MAX_NUM_ARGS]);
290 
291 /** Add all args from a given factory to the argc/argv passed as parameters, which could
292  * include recursing into another ArgFactory.
293  */
294 static void lAddArgsFromFactory(ArgFactory &Args, int &argc, char *argv[MAX_NUM_ARGS]) {
295  while (true) {
296  char *NextArg = Args.GetNextArg();
297  if (NextArg == NULL)
298  break;
299  lAddSingleArg(NextArg, argc, argv);
300  }
301 }
302 
303 /** Parse an open file for arguments and add them to the argc/argv passed as parameters */
304 static void lAddArgsFromFile(FILE *file, int &argc, char *argv[MAX_NUM_ARGS]) {
305  FileArgFactory args(file);
306  lAddArgsFromFactory(args, argc, argv);
307 }
308 
309 /** Parse a string for arguments and add them to the argc/argv passed as parameters */
310 static void lAddArgsFromString(const char *string, int &argc, char *argv[MAX_NUM_ARGS]) {
311  StringArgFactory args(string);
312  lAddArgsFromFactory(args, argc, argv);
313 }
314 
315 /** Add a single argument to the argc/argv passed as parameters. If the argument is of the
316  * form @<filename> and <filename> exists and is readable, the arguments in the file will be
317  * inserted into argc/argv in place of the original argument.
318  */
319 static void lAddSingleArg(char *arg, int &argc, char *argv[MAX_NUM_ARGS]) {
320  if (arg[0] == '@') {
321  char *filename = &arg[1];
322  FILE *file = fopen(filename, "r");
323  if (file != NULL) {
324  lAddArgsFromFile(file, argc, argv);
325  fclose(file);
326  arg = NULL;
327  }
328  }
329  if (arg != NULL) {
330  if (argc >= MAX_NUM_ARGS) {
331  fprintf(stderr, "More than %d arguments have been specified - aborting\n", MAX_NUM_ARGS);
332  exit(EXIT_FAILURE);
333  }
334  // printf("Arg %d: %s\n", argc, arg);
335  argv[argc++] = arg;
336  }
337 }
338 
339 /** We take arguments from both the command line as well as from the
340  * ISPC_ARGS environment variable - and each of these can include a file containing
341  * additional arguments using @<filename>. This function returns a new set of
342  * arguments representing the ones from all these sources merged together.
343  */
344 static void lGetAllArgs(int Argc, char *Argv[], int &argc, char *argv[MAX_NUM_ARGS]) {
345  argc = 0;
346 
347  // Copy over the command line arguments (passed in)
348  for (int i = 0; i < Argc; ++i)
349  lAddSingleArg(Argv[i], argc, argv);
350 
351  // See if we have any set via the environment variable
352  const char *env = getenv("ISPC_ARGS");
353  if (env)
354  lAddArgsFromString(env, argc, argv);
355 }
356 
357 static void lSignal(void *) { FATAL("Unhandled signal sent to process; terminating."); }
358 
359 static int ParsingPhaseName(char *stage) {
360  if (strncmp(stage, "first", 5) == 0) {
361  return 0;
362  } else if (strncmp(stage, "last", 4) == 0) {
363  return LAST_OPT_NUMBER;
364  } else {
365  int t = atoi(stage);
366  if (t < 0 || t > LAST_OPT_NUMBER) {
367  fprintf(stderr, "Phases must be from 0 to %d. %s is incorrect.\n", LAST_OPT_NUMBER, stage);
368  exit(0);
369  } else {
370  return t;
371  }
372  }
373 }
374 
375 static std::set<int> ParsingPhases(char *stages) {
376  std::set<int> phases;
377  auto len = strnlen(stages, 100);
378  Assert(len && len < 100 && "phases string is too long!");
379  int begin = ParsingPhaseName(stages);
380  int end = begin;
381 
382  for (unsigned i = 0; i < strlen(stages); i++) {
383  if ((stages[i] == ',') || (i == strlen(stages) - 1)) {
384  for (int j = begin; j < end + 1; j++) {
385  phases.insert(j);
386  }
387  begin = ParsingPhaseName(stages + i + 1);
388  end = begin;
389  } else if (stages[i] == ':') {
390  end = ParsingPhaseName(stages + i + 1);
391  }
392  }
393  return phases;
394 }
395 
396 static void lParseInclude(const char *path) {
397 #ifdef ISPC_HOST_IS_WINDOWS
398  char delim = ';';
399 #else
400  char delim = ':';
401 #endif
402  size_t pos = 0, pos_end;
403  std::string str_path(path);
404  do {
405  pos_end = str_path.find(delim, pos);
406  size_t len = (pos_end == std::string::npos) ?
407  // Not found, copy till end of the string.
408  std::string::npos
409  :
410  // Copy [pos, pos_end).
411  (pos_end - pos);
412  std::string s = str_path.substr(pos, len);
413  g->includePath.push_back(s);
414  pos = pos_end + 1;
415  } while (pos_end != std::string::npos);
416 }
417 
418 int main(int Argc, char *Argv[]) {
419  int argc;
420  char *argv[MAX_NUM_ARGS];
421  lGetAllArgs(Argc, Argv, argc, argv);
422 
423  llvm::sys::AddSignalHandler(lSignal, NULL);
424 
425  // initialize available LLVM targets
426  // TO-DO : Revisit after experimenting on arm and aarch64 hardware.
427 #ifndef __arm__
428  // FIXME: LLVM build on ARM doesn't build the x86 targets by default.
429  // It's not clear that anyone's going to want to generate x86 from an
430  // ARM host, though...
431  LLVMInitializeX86TargetInfo();
432  LLVMInitializeX86Target();
433  LLVMInitializeX86AsmPrinter();
434  LLVMInitializeX86AsmParser();
435  LLVMInitializeX86Disassembler();
436  LLVMInitializeX86TargetMC();
437 #endif // !__ARM__
438 
439 #ifdef ISPC_ARM_ENABLED
440  // Generating ARM and AARCH64 from x86 is more likely to be useful, though.
441  LLVMInitializeARMTargetInfo();
442  LLVMInitializeARMTarget();
443  LLVMInitializeARMAsmPrinter();
444  LLVMInitializeARMAsmParser();
445  LLVMInitializeARMDisassembler();
446  LLVMInitializeARMTargetMC();
447 
448  LLVMInitializeAArch64TargetInfo();
449  LLVMInitializeAArch64Target();
450  LLVMInitializeAArch64AsmPrinter();
451  LLVMInitializeAArch64AsmParser();
452  LLVMInitializeAArch64Disassembler();
453  LLVMInitializeAArch64TargetMC();
454 #endif
455 
456 #ifdef ISPC_NVPTX_ENABLED
457  LLVMInitializeNVPTXTargetInfo();
458  LLVMInitializeNVPTXTarget();
459  LLVMInitializeNVPTXAsmPrinter();
460  LLVMInitializeNVPTXTargetMC();
461 #endif /* ISPC_NVPTX_ENABLED */
462 
463  char *file = NULL;
464  const char *headerFileName = NULL;
465  const char *outFileName = NULL;
466  const char *includeFileName = NULL;
467  const char *depsFileName = NULL;
468  const char *depsTargetName = NULL;
469  const char *hostStubFileName = NULL;
470  const char *devStubFileName = NULL;
471  // Initiailize globals early so that we can set various option values
472  // as we're parsing below
473  g = new Globals;
474 
477  const char *arch = NULL, *cpu = NULL, *target = NULL, *intelAsmSyntax = NULL;
478 
479  // Default settings for PS4
480  if (g->target_os == TargetOS::OS_PS4) {
481  flags |= Module::GeneratePIC;
482  cpu = "btver2";
483  }
484  for (int i = 1; i < argc; ++i) {
485  if (!strcmp(argv[i], "--help"))
486  usage(0);
487  if (!strcmp(argv[i], "--help-dev"))
488  devUsage(0);
489  else if (!strncmp(argv[i], "-D", 2))
490  g->cppArgs.push_back(argv[i]);
491  else if (!strncmp(argv[i], "--addressing=", 13)) {
492  if (atoi(argv[i] + 13) == 64)
493  // FIXME: this doesn't make sense on 32 bit platform.
494  g->opt.force32BitAddressing = false;
495  else if (atoi(argv[i] + 13) == 32)
496  g->opt.force32BitAddressing = true;
497  else {
498  fprintf(stderr,
499  "Addressing width \"%s\" invalid--only 32 and "
500  "64 are allowed.\n",
501  argv[i] + 13);
502  usage(1);
503  }
504  } else if (!strncmp(argv[i], "--arch=", 7)) {
505  // Do not allow to set arch for PS4 target, it is pre-defined.
506  if (g->target_os != TargetOS::OS_PS4) {
507  arch = argv[i] + 7;
508  // Define arch alias
509  // LLVM TargetRegistry uses "x86-64", while triple uses "x86_64".
510  // We support both as input and internally keep it as "x86-64".
511  if (std::string(arch) == "x86_64") {
512  arch = "x86-64";
513  }
514  }
515  } else if (!strncmp(argv[i], "--x86-asm-syntax=", 17)) {
516  intelAsmSyntax = argv[i] + 17;
517  if (!((std::string(intelAsmSyntax) == "intel") || (std::string(intelAsmSyntax) == "att"))) {
518  intelAsmSyntax = NULL;
519  fprintf(stderr,
520  "Invalid value for --x86-asm-syntax: \"%s\" -- "
521  "only intel and att are allowed.\n",
522  argv[i] + 17);
523  }
524  } else if (!strncmp(argv[i], "--cpu=", 6)) {
525  // Do not allow to set cpu for PS4 target, it is pre-defined.
526  if (g->target_os != TargetOS::OS_PS4) {
527  cpu = argv[i] + 6;
528  }
529  } else if (!strcmp(argv[i], "--fast-math")) {
530  fprintf(stderr, "--fast-math option has been renamed to --opt=fast-math!\n");
531  usage(1);
532  } else if (!strcmp(argv[i], "--fast-masked-vload")) {
533  fprintf(stderr, "--fast-masked-vload option has been renamed to "
534  "--opt=fast-masked-vload!\n");
535  usage(1);
536  } else if (!strcmp(argv[i], "--debug"))
537  g->debugPrint = true;
538  else if (!strcmp(argv[i], "--debug-llvm"))
539  llvm::DebugFlag = true;
540  else if (!strcmp(argv[i], "--dllexport"))
541  g->dllExport = true;
542 #if ISPC_LLVM_VERSION >= ISPC_LLVM_3_5
543  else if (!strncmp(argv[i], "--dwarf-version=", 16)) {
544  int val = atoi(argv[i] + 16);
545  if (2 <= val && val <= 4) {
546  g->generateDebuggingSymbols = true;
547  g->generateDWARFVersion = val;
548  } else {
549  fprintf(stderr,
550  "Invalid value for DWARF version: \"%s\" -- "
551  "only 2, 3 and 4 are allowed.\n",
552  argv[i] + 16);
553  usage(1);
554  }
555  }
556 #endif
557  else if (!strcmp(argv[i], "--print-target"))
558  g->printTarget = true;
559  else if (!strcmp(argv[i], "--no-omit-frame-pointer"))
560  g->NoOmitFramePointer = true;
561  else if (!strcmp(argv[i], "--instrument"))
562  g->emitInstrumentation = true;
563  else if (!strcmp(argv[i], "--no-pragma-once"))
564  g->noPragmaOnce = true;
565  else if (!strcmp(argv[i], "-g")) {
566  g->generateDebuggingSymbols = true;
567  } else if (!strcmp(argv[i], "--emit-asm"))
568  ot = Module::Asm;
569  else if (!strcmp(argv[i], "--emit-c++"))
570  ot = Module::CXX;
571  else if (!strcmp(argv[i], "--emit-llvm"))
572  ot = Module::Bitcode;
573  else if (!strcmp(argv[i], "--emit-llvm-text"))
574  ot = Module::BitcodeText;
575  else if (!strcmp(argv[i], "--emit-obj"))
576  ot = Module::Object;
577  else if (!strcmp(argv[i], "-I")) {
578  if (++i == argc) {
579  fprintf(stderr, "No path specified after -I option.\n");
580  usage(1);
581  }
582  lParseInclude(argv[i]);
583  } else if (!strncmp(argv[i], "-I", 2))
584  lParseInclude(argv[i] + 2);
585  else if (!strcmp(argv[i], "--fuzz-test"))
586  g->enableFuzzTest = true;
587  else if (!strncmp(argv[i], "--fuzz-seed=", 12))
588  g->fuzzTestSeed = atoi(argv[i] + 12);
589  else if (!strcmp(argv[i], "--target")) {
590  // FIXME: should remove this way of specifying the target...
591  if (++i == argc) {
592  fprintf(stderr, "No target specified after --target option.\n");
593  usage(1);
594  }
595  target = argv[i];
596  } else if (!strncmp(argv[i], "--target=", 9)) {
597  target = argv[i] + 9;
598  } else if (!strncmp(argv[i], "--target-os=", 12)) {
599  g->target_os = StringToOS(argv[i] + 12);
600  if (g->target_os == OS_ERROR) {
601  fprintf(stderr, "Unsupported value for --target-os, supported values are: %s\n",
603  usage(1);
604  }
605  } else if (!strncmp(argv[i], "--math-lib=", 11)) {
606  const char *lib = argv[i] + 11;
607  if (!strcmp(lib, "default"))
609  else if (!strcmp(lib, "fast"))
611  else if (!strcmp(lib, "svml"))
613  else if (!strcmp(lib, "system"))
615  else {
616  fprintf(stderr, "Unknown --math-lib= option \"%s\".\n", lib);
617  usage(1);
618  }
619  } else if (!strncmp(argv[i], "--opt=", 6)) {
620  const char *opt = argv[i] + 6;
621  if (!strcmp(opt, "fast-math"))
622  g->opt.fastMath = true;
623  else if (!strcmp(opt, "fast-masked-vload"))
624  g->opt.fastMaskedVload = true;
625  else if (!strcmp(opt, "disable-assertions"))
626  g->opt.disableAsserts = true;
627  else if (!strcmp(opt, "disable-loop-unroll"))
628  g->opt.unrollLoops = false;
629  else if (!strcmp(opt, "disable-fma"))
630  g->opt.disableFMA = true;
631  else if (!strcmp(opt, "force-aligned-memory"))
632  g->opt.forceAlignedMemory = true;
633 
634  // These are only used for performance tests of specific
635  // optimizations
636  else if (!strcmp(opt, "disable-all-on-optimizations"))
638  else if (!strcmp(opt, "disable-coalescing"))
639  g->opt.disableCoalescing = true;
640  else if (!strcmp(opt, "disable-handle-pseudo-memory-ops"))
642  else if (!strcmp(opt, "disable-blended-masked-stores"))
644  else if (!strcmp(opt, "disable-coherent-control-flow"))
646  else if (!strcmp(opt, "disable-uniform-control-flow"))
648  else if (!strcmp(opt, "disable-gather-scatter-optimizations"))
650  else if (!strcmp(opt, "disable-blending-removal"))
652  else if (!strcmp(opt, "disable-gather-scatter-flattening"))
654  else if (!strcmp(opt, "disable-uniform-memory-optimizations"))
656  else {
657  fprintf(stderr, "Unknown --opt= option \"%s\".\n", opt);
658  usage(1);
659  }
660  } else if (!strncmp(argv[i], "--force-alignment=", 18)) {
661  g->forceAlignment = atoi(argv[i] + 18);
662  } else if (!strcmp(argv[i], "--woff") || !strcmp(argv[i], "-woff")) {
663  g->disableWarnings = true;
664  g->emitPerfWarnings = false;
665  } else if (!strcmp(argv[i], "--werror"))
666  g->warningsAsErrors = true;
667  else if (!strcmp(argv[i], "--nowrap"))
668  g->disableLineWrap = true;
669  else if (!strcmp(argv[i], "--wno-perf") || !strcmp(argv[i], "-wno-perf"))
670  g->emitPerfWarnings = false;
671  else if (!strcmp(argv[i], "-o")) {
672  if (++i == argc) {
673  fprintf(stderr, "No output file specified after -o option.\n");
674  usage(1);
675  }
676  outFileName = argv[i];
677  } else if (!strncmp(argv[i], "--outfile=", 10))
678  outFileName = argv[i] + strlen("--outfile=");
679  else if (!strcmp(argv[i], "-h")) {
680  if (++i == argc) {
681  fprintf(stderr, "No header file name specified after -h option.\n");
682  usage(1);
683  }
684  headerFileName = argv[i];
685  } else if (!strncmp(argv[i], "--header-outfile=", 17)) {
686  headerFileName = argv[i] + strlen("--header-outfile=");
687  } else if (!strncmp(argv[i], "--c++-include-file=", 19)) {
688  includeFileName = argv[i] + strlen("--c++-include-file=");
689  } else if (!strcmp(argv[i], "-O0")) {
690  g->opt.level = 0;
691  g->codegenOptLevel = Globals::CodegenOptLevel::None;
692  } else if (!strcmp(argv[i], "-O") || !strcmp(argv[i], "-O1") || !strcmp(argv[i], "-O2") ||
693  !strcmp(argv[i], "-O3")) {
694  g->opt.level = 1;
695  g->codegenOptLevel = Globals::CodegenOptLevel::Aggressive;
696  if (!strcmp(argv[i], "-O1"))
698  } else if (!strcmp(argv[i], "-"))
699  ;
700  else if (!strcmp(argv[i], "--nostdlib"))
701  g->includeStdlib = false;
702  else if (!strcmp(argv[i], "--nocpp"))
703  g->runCPP = false;
704  else if (!strcmp(argv[i], "--pic"))
705  flags |= Module::GeneratePIC;
706 #ifndef ISPC_IS_HOST_WINDOWS
707  else if (!strcmp(argv[i], "--colored-output"))
708  g->forceColoredOutput = true;
709 #endif // !ISPC_IS_HOST_WINDOWS
710  else if (!strcmp(argv[i], "--quiet"))
711  g->quiet = true;
712  else if (!strcmp(argv[i], "--yydebug")) {
713  extern int yydebug;
714  yydebug = 1;
715  } else if (!strcmp(argv[i], "-MMM")) {
716  if (++i == argc) {
717  fprintf(stderr, "No output file name specified after -MMM option.\n");
718  usage(1);
719  }
720  depsFileName = argv[i];
721  flags |= Module::GenerateFlatDeps;
722  } else if (!strcmp(argv[i], "-M")) {
724  } else if (!strcmp(argv[i], "-MF")) {
725  depsFileName = nullptr;
726  if (++i == argc) {
727  fprintf(stderr, "No output file name specified after -MF option.\n");
728  usage(1);
729  }
730  depsFileName = argv[i];
731  } else if (!strcmp(argv[i], "-MT")) {
732  depsTargetName = nullptr;
733  if (++i == argc) {
734  fprintf(stderr, "No target name specified after -MT option.\n");
735  usage(1);
736  }
737  depsTargetName = argv[i];
738  } else if (!strcmp(argv[i], "--dev-stub")) {
739  if (++i == argc) {
740  fprintf(stderr, "No output file name specified after --dev-stub option.\n");
741  usage(1);
742  }
743  devStubFileName = argv[i];
744  } else if (!strcmp(argv[i], "--host-stub")) {
745  if (++i == argc) {
746  fprintf(stderr, "No output file name specified after --host-stub option.\n");
747  usage(1);
748  }
749  hostStubFileName = argv[i];
750  }
751 #ifndef ISPC_NO_DUMPS
752  else if (strncmp(argv[i], "--debug-phase=", 14) == 0) {
753  fprintf(stderr, "WARNING: Adding debug phases may change the way PassManager"
754  "handles the phases and it may possibly make some bugs go"
755  "away or introduce the new ones.\n");
756  g->debug_stages = ParsingPhases(argv[i] + strlen("--debug-phase="));
757  } else if (strncmp(argv[i], "--dump-file", 11) == 0)
758  g->dumpFile = true;
759 #endif
760 
761 #if ISPC_LLVM_VERSION == ISPC_LLVM_3_4 || ISPC_LLVM_VERSION == ISPC_LLVM_3_5 // 3.4, 3.5
762  else if (strncmp(argv[i], "--debug-ir=", 11) == 0) {
763  g->debugIR = ParsingPhaseName(argv[i] + strlen("--debug-ir="));
764  }
765 #endif
766  else if (strncmp(argv[i], "--off-phase=", 12) == 0) {
767  g->off_stages = ParsingPhases(argv[i] + strlen("--off-phase="));
768  } else if (!strcmp(argv[i], "-v") || !strcmp(argv[i], "--version")) {
769  lPrintVersion();
770  return 0;
771  } else if (argv[i][0] == '-') {
772  fprintf(stderr, "Unknown option \"%s\".\n", argv[i]);
773  usage(1);
774  } else {
775  if (file != NULL) {
776  fprintf(stderr,
777  "Multiple input files specified on command "
778  "line: \"%s\" and \"%s\".\n",
779  file, argv[i]);
780  usage(1);
781  } else
782  file = argv[i];
783  }
784  }
785 
786  if (g->enableFuzzTest) {
787  if (g->fuzzTestSeed == -1) {
788 #ifdef ISPC_HOST_IS_WINDOWS
789  int seed = (unsigned)time(NULL);
790 #else
791  int seed = getpid();
792 #endif
793  g->fuzzTestSeed = seed;
794  Warning(SourcePos(), "Using seed %d for fuzz testing", g->fuzzTestSeed);
795  }
796 #ifdef ISPC_HOST_IS_WINDOWS
797  srand(g->fuzzTestSeed);
798 #else
799  srand48(g->fuzzTestSeed);
800 #endif
801  }
802 
803  if (depsFileName != NULL)
804  flags &= ~Module::OutputDepsToStdout;
805 
806  if (depsFileName != NULL && 0 == (flags & (Module::GenerateFlatDeps | Module::GenerateMakeRuleForDeps))) {
807  Warning(SourcePos(), "Dependency file name specified with -MF, but no "
808  "mode specified; did you forget to specify -M or -MMM? "
809  "No dependency output will be generated.");
810  depsFileName = NULL;
811  }
812 
815  Warning(SourcePos(), "Both -M and -MMM specified on the command line. "
816  "-MMM takes precedence.");
818  }
819 
820  if (outFileName == NULL && headerFileName == NULL &&
821  (depsFileName == NULL && 0 == (flags & Module::OutputDepsToStdout)) && hostStubFileName == NULL &&
822  devStubFileName == NULL)
823  Warning(SourcePos(), "No output file or header file name specified. "
824  "Program will be compiled and warnings/errors will "
825  "be issued, but no output will be generated.");
826 
827  if (g->target_os == OS_WINDOWS && (flags & Module::GeneratePIC) != 0) {
828  Warning(SourcePos(), "--pic switch for Windows target will be ignored.");
829  }
830 
831  if (g->target_os != OS_WINDOWS && g->dllExport) {
832  Warning(SourcePos(), "--dllexport switch will be ignored, as the target OS is not Windows.");
833  }
834 
835  if ((ot == Module::Asm) && (intelAsmSyntax != NULL)) {
836  std::vector<const char *> Args(3);
837  Args[0] = "ispc (LLVM option parsing)";
838  Args[2] = nullptr;
839  if (std::string(intelAsmSyntax) == "intel")
840  Args[1] = "--x86-asm-syntax=intel";
841  else
842  Args[1] = "--x86-asm-syntax=att";
843  llvm::cl::ParseCommandLineOptions(2, Args.data());
844  }
845 
846  return Module::CompileAndOutput(file, arch, cpu, target, flags, ot, outFileName, headerFileName, includeFileName,
847  depsFileName, depsTargetName, hostStubFileName, devStubFileName);
848 }
bool disableFMA
Definition: ispc.h:460
TargetOS target_os
Definition: ispc.h:547
Definition: ispc.h:119
Opt opt
Definition: ispc.h:542
bool disableWarnings
Definition: ispc.h:590
This structure collects together a number of global variables.
Definition: ispc.h:538
bool disableBlendedMaskedStores
Definition: ispc.h:487
static int CompileAndOutput(const char *srcFile, const char *arch, const char *cpu, const char *targets, OutputFlags outputFlags, OutputType outputType, const char *outFileName, const char *headerFileName, const char *includeFileName, const char *depsFileName, const char *depsTargetName, const char *hostStubFileName, const char *devStubFileName)
Definition: module.cpp:2991
static void lSignal(void *)
Definition: main.cpp:357
bool forceColoredOutput
Definition: ispc.h:608
virtual char GetNextChar()=0
std::vector< std::string > includePath
Definition: ispc.h:657
bool emitPerfWarnings
Definition: ispc.h:601
bool warningsAsErrors
Definition: ispc.h:593
bool NoOmitFramePointer
Definition: ispc.h:574
static void lAddArgsFromFile(FILE *file, int &argc, char *argv[MAX_NUM_ARGS])
Definition: main.cpp:304
static void lAddSingleArg(char *arg, int &argc, char *argv[MAX_NUM_ARGS])
Definition: main.cpp:319
bool forceAlignedMemory
Definition: ispc.h:466
char * AllocateString(std::string string)
Definition: main.cpp:215
static void lGetAllArgs(int Argc, char *Argv[], int &argc, char *argv[MAX_NUM_ARGS])
Definition: main.cpp:344
int fuzzTestSeed
Definition: ispc.h:642
static const char * SupportedArchs()
Definition: ispc.cpp:1204
OutputType
Definition: module.h:91
static void devUsage(int ret)
Definition: main.cpp:178
bool disableLineWrap
Definition: ispc.h:597
bool disableCoalescing
Definition: ispc.h:527
#define Assert(expr)
Definition: ispc.h:163
virtual char GetNextChar()
Definition: main.cpp:275
ArgFactory()
Definition: main.cpp:228
bool includeStdlib
Definition: ispc.h:560
std::set< int > debug_stages
Definition: ispc.h:577
bool disableMaskAllOnOptimizations
Definition: ispc.h:471
int level
Definition: ispc.h:432
static void lAddArgsFromString(const char *string, int &argc, char *argv[MAX_NUM_ARGS])
Definition: main.cpp:310
static std::string SupportedCPUs()
Definition: ispc.cpp:1199
Globals * g
Definition: ispc.cpp:101
bool disableGatherScatterOptimizations
Definition: ispc.h:505
bool debugPrint
Definition: ispc.h:568
bool disableCoherentControlFlow
Definition: ispc.h:493
static void lPrintVersion()
Definition: main.cpp:69
bool enableFuzzTest
Definition: ispc.h:639
bool printTarget
Definition: ispc.h:571
Definition: module.h:56
void PrintWithWordBreaks(const char *buf, int indent, int columnWidth, FILE *out)
Definition: util.cpp:210
FILE * InputFile
Definition: main.cpp:255
int TerminalWidth()
Definition: util.cpp:80
const char * InputString
Definition: main.cpp:273
bool runCPP
Definition: ispc.h:564
CodegenOptLevel codegenOptLevel
Definition: ispc.h:556
bool emitInstrumentation
Definition: ispc.h:614
bool unrollLoops
Definition: ispc.h:446
Representation of a range of positions in a source file.
Definition: ispc.h:131
bool disableUniformMemoryOptimizations
Definition: ispc.h:523
bool generateDebuggingSymbols
Definition: ispc.h:620
bool fastMath
Definition: ispc.h:436
static void lAddArgsFromFactory(ArgFactory &Args, int &argc, char *argv[MAX_NUM_ARGS])
Definition: main.cpp:294
static void lParseInclude(const char *path)
Definition: main.cpp:396
bool fastMaskedVload
Definition: ispc.h:442
bool disableHandlePseudoMemoryOps
Definition: ispc.h:477
bool force32BitAddressing
Definition: ispc.h:452
bool dllExport
Definition: ispc.h:664
void Warning(SourcePos p, const char *format,...) PRINTF_FUNC
Definition: util.cpp:375
int main(int Argc, char *Argv[])
Definition: main.cpp:418
#define FATAL(message)
Definition: util.h:112
StringArgFactory(const char *string)
Definition: main.cpp:285
MathLib mathLib
Definition: ispc.h:552
bool disableUniformControlFlow
Definition: ispc.h:499
bool disableMaskedStoreToStore
Definition: ispc.h:511
Definition: ispc.h:119
OutputFlags
Definition: module.h:105
bool dumpFile
Definition: ispc.h:580
char * GetNextArg()
Definition: main.cpp:230
int forceAlignment
Definition: ispc.h:661
static const char * SupportedOSes()
Definition: ispc.cpp:1238
static int ParsingPhaseName(char *stage)
Definition: main.cpp:359
bool quiet
Definition: ispc.h:604
std::set< int > off_stages
Definition: ispc.h:587
bool noPragmaOnce
Definition: ispc.h:616
TargetOS StringToOS(std::string)
Definition: ispc.cpp:1672
std::vector< std::string > cppArgs
Definition: ispc.h:653
virtual char GetNextChar()
Definition: main.cpp:257
static std::set< int > ParsingPhases(char *stages)
Definition: main.cpp:375
Declaration of the Module class, which is the ispc-side representation of the results of compiling a ...
static const char * SupportedTargets()
Definition: ispc.cpp:1212
#define LAST_OPT_NUMBER
Definition: ispc.h:69
Main ispc.header file. Defines Target, Globals and Opt classes.
static void usage(int ret)
Definition: main.cpp:89
bool disableAsserts
Definition: ispc.h:456
#define MAX_NUM_ARGS
Definition: main.cpp:67
File with declarations for classes related to type representation.
bool disableGatherScatterFlattening
Definition: ispc.h:517
FileArgFactory(FILE *file)
Definition: main.cpp:267
int debugIR
Definition: ispc.h:584