Intel SPMD Program Compiler  1.11.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_IS_WINDOWS
45 #include <time.h>
46 #else
47 #include <unistd.h>
48 #endif // ISPC_IS_WINDOWS
49 #include <llvm/Support/Signals.h>
50 #include <llvm/Support/TargetRegistry.h>
51 #include <llvm/Support/TargetSelect.h>
52 
53 #ifdef ISPC_IS_WINDOWS
54 #define strcasecmp stricmp
55 #ifndef BUILD_DATE
56 #define BUILD_DATE __DATE__
57 #endif
58 #define BUILD_VERSION ""
59 #if _MSC_VER >= 1900
60 #define ISPC_VS_VERSION "Visual Studio 2015 and later"
61 #else
62 #define ISPC_VS_VERSION "Visual Studio 2013 and earlier"
63 #endif
64 #endif // ISPC_IS_WINDOWS
65 
66 #define MAX_NUM_ARGS (512)
67 
68 static void lPrintVersion() {
69 #ifdef ISPC_IS_WINDOWS
70  printf("Intel(r) SPMD Program Compiler (ispc), %s (build date %s, LLVM %s)\n"
71  "Supported Visual Studio versions: %s.\n",
72  ISPC_VERSION, BUILD_DATE, ISPC_LLVM_VERSION_STRING, ISPC_VS_VERSION);
73 #else
74  printf("Intel(r) SPMD Program Compiler (ispc), %s (build %s @ %s, LLVM %s)\n", ISPC_VERSION, BUILD_VERSION,
75  BUILD_DATE, ISPC_LLVM_VERSION_STRING);
76 #endif
77 
78 // The recommended way to build ISPC assumes custom LLVM build with a set of patches.
79 // If the default LLVM distribution is used, then the resuling ISPC binary may contain
80 // known and already fixed stability and performance problems.
81 #ifdef ISPC_NO_DUMPS
82  printf("This version is likely linked against non-recommended LLVM binaries.\n"
83  "For best stability and performance please use official binary distribution from "
84  "http://ispc.github.io/downloads.html");
85 #endif
86 }
87 
88 static void usage(int ret) {
89  lPrintVersion();
90  printf("\nusage: ispc\n");
91  printf(" [--addressing={32,64}]\t\tSelect 32- or 64-bit addressing. (Note that 32-bit\n");
92  printf(" \t\taddressing calculations are done by default, even\n");
93  printf(" \t\ton 64-bit target architectures.)\n");
94  printf(" [--arch={%s}]\t\tSelect target architecture\n", Target::SupportedArchs());
95  printf(" [--c++-include-file=<name>]\t\tSpecify name of file to emit in #include statement in generated C++ "
96  "code.\n");
97 #ifndef ISPC_IS_WINDOWS
98  printf(" [--colored-output]\t\tAlways use terminal colors in error/warning messages.\n");
99 #endif
100  printf(" ");
101  char cpuHelp[2048];
102  snprintf(cpuHelp, sizeof(cpuHelp), "[--cpu=<cpu>]\t\t\tSelect target CPU type\n<cpu>={%s}\n",
103  Target::SupportedCPUs().c_str());
104  PrintWithWordBreaks(cpuHelp, 16, TerminalWidth(), stdout);
105  printf(" [-D<foo>]\t\t\t\t#define given value when running preprocessor\n");
106  printf(" [--dev-stub <filename>]\t\tEmit device-side offload stub functions to file\n");
107 #ifdef ISPC_IS_WINDOWS
108  printf(" [--dllexport]\t\t\tMake non-static functions DLL exported. Windows only.\n");
109 #endif
110 #if ISPC_LLVM_VERSION >= ISPC_LLVM_3_5
111  printf(" [--dwarf-version={2,3,4}]\t\tGenerate source-level debug information with given DWARF version "
112  "(triggers -g)\n");
113 #endif
114  printf(" [--emit-asm]\t\t\tGenerate assembly language file as output\n");
115  printf(" [--x86-asm-syntax=<option>]\t\tSelect style of code if generating assembly\n");
116  printf(" intel\t\t\t\tEmit Intel-style assembly\n");
117  printf(" att\t\t\t\tEmit AT&T-style assembly\n");
118  printf(" [--emit-c++]\t\t\tEmit a C++ source file as output\n");
119  printf(" [--emit-llvm]\t\t\tEmit LLVM bitode file as output\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 #ifndef ISPC_IS_WINDOWS
157  printf(" [--pic]\t\t\t\tGenerate position-independent code\n");
158 #endif // !ISPC_IS_WINDOWS
159  printf(" [--quiet]\t\t\t\tSuppress all output\n");
160  printf(" ");
161  char targetHelp[2048];
162  snprintf(targetHelp, sizeof(targetHelp),
163  "[--target=<t>]\t\t\tSelect target ISA and width.\n"
164  "<t>={%s}",
166  PrintWithWordBreaks(targetHelp, 24, TerminalWidth(), stdout);
167  printf(" [--version]\t\t\t\tPrint ispc version\n");
168  printf(" [--werror]\t\t\t\tTreat warnings as errors\n");
169  printf(" [--woff]\t\t\t\tDisable warnings\n");
170  printf(" [--wno-perf]\t\t\tDon't issue warnings related to performance-related issues\n");
171  printf(" [@<filename>]\t\t\tRead additional arguments from the given file\n");
172  printf(" <file to compile or \"-\" for stdin>\n");
173  exit(ret);
174 }
175 
176 static void devUsage(int ret) {
177  lPrintVersion();
178  printf("\nusage (developer options): ispc\n");
179  printf(" [--debug]\t\t\t\tPrint information useful for debugging ispc\n");
180  printf(" [--print-target]\t\t\tPrint target's information\n");
181  printf(" [--fuzz-test]\t\t\tRandomly perturb program input to test error conditions\n");
182  printf(" [--fuzz-seed=<value>]\t\tSeed value for RNG for fuzz testing\n");
183  printf(" [--opt=<option>]\t\t\tSet optimization option\n");
184  printf(" disable-all-on-optimizations\t\tDisable optimizations that take advantage of \"all on\" mask\n");
185  printf(" disable-blended-masked-stores\t\tScalarize masked stores on SSE (vs. using vblendps)\n");
186  printf(" disable-blending-removal\t\tDisable eliminating blend at same scope\n");
187  printf(" disable-coalescing\t\t\tDisable gather coalescing\n");
188  printf(" disable-coherent-control-flow\t\tDisable coherent control flow optimizations\n");
189  printf(" disable-gather-scatter-flattening\tDisable flattening when all lanes are on\n");
190  printf(" disable-gather-scatter-optimizations\tDisable improvements to gather/scatter\n");
191  printf(" disable-handle-pseudo-memory-ops\tLeave __pseudo_* calls for gather/scatter/etc. in final IR\n");
192  printf(" disable-uniform-control-flow\t\tDisable uniform control flow optimizations\n");
193  printf(" disable-uniform-memory-optimizations\tDisable uniform-based coherent memory access\n");
194  printf(" [--yydebug]\t\t\t\tPrint debugging information during parsing\n");
195 #ifndef ISPC_NO_DUMPS
196  printf(" [--debug-phase=<value>]\t\tSet optimization phases to dump. "
197  "--debug-phase=first,210:220,300,305,310:last\n");
198 #endif
199 #if ISPC_LLVM_VERSION == ISPC_LLVM_3_4 || ISPC_LLVM_VERSION == ISPC_LLVM_3_5 // 3.4, 3.5
200  printf(" [--debug-ir=<value>]\t\tSet optimization phase to generate debugIR after it\n");
201 #endif
202  printf(" [--off-phase=<value>]\t\tSwitch off optimization phases. --off-phase=first,210:220,300,305,310:last\n");
203  exit(ret);
204 }
205 
206 /** Define an abstract base-class that implements the parsing of an character source and
207  * the breaking of it into the individual arguments
208  */
209 class ArgFactory {
210  private:
211  char *AllocateString(std::string string) {
212  int len = string.length();
213  char *ptr = new char[len + 1];
214  strncpy(ptr, string.c_str(), len);
215  ptr[len] = '\0';
216  return ptr;
217  }
218 
219  /** Method provided by the derived classes to retrieve the next character from the stream.
220  */
221  virtual char GetNextChar() = 0;
222 
223  public:
225 
226  char *GetNextArg() {
227  std::string arg;
228  char c = GetNextChar();
229 
230  // First consume any white-space before the argument
231  while (isspace(c))
232  c = GetNextChar();
233 
234  if (c == '\0')
235  // Reached the end so no more arguments
236  return NULL;
237 
238  // c now has the first character of the next argument, so collect the rest
239  while (c != '\0' && !isspace(c)) {
240  arg += c;
241  c = GetNextChar();
242  }
243 
244  return AllocateString(arg);
245  }
246 };
247 
248 /** Define a class to break the contents of an open file into the individual arguments */
249 class FileArgFactory : public ArgFactory {
250  private:
251  FILE *InputFile;
252 
253  virtual char GetNextChar() {
254  int c = fgetc(InputFile);
255  if (c == EOF) {
256  return '\0';
257  } else {
258  return c;
259  }
260  }
261 
262  public:
263  FileArgFactory(FILE *file) : InputFile(file) {}
264 };
265 
266 /** Define a class to break a NUL-terminated string into the individual arguments */
267 class StringArgFactory : public ArgFactory {
268  private:
269  const char *InputString;
270 
271  virtual char GetNextChar() {
272  char c = *InputString;
273 
274  if (c != '\0')
275  ++InputString;
276 
277  return c;
278  }
279 
280  public:
281  StringArgFactory(const char *string) : InputString(string) {}
282 };
283 
284 // Forward reference
285 static void lAddSingleArg(char *arg, int &argc, char *argv[MAX_NUM_ARGS]);
286 
287 /** Add all args from a given factory to the argc/argv passed as parameters, which could
288  * include recursing into another ArgFactory.
289  */
290 static void lAddArgsFromFactory(ArgFactory &Args, int &argc, char *argv[MAX_NUM_ARGS]) {
291  while (true) {
292  char *NextArg = Args.GetNextArg();
293  if (NextArg == NULL)
294  break;
295  lAddSingleArg(NextArg, argc, argv);
296  }
297 }
298 
299 /** Parse an open file for arguments and add them to the argc/argv passed as parameters */
300 static void lAddArgsFromFile(FILE *file, int &argc, char *argv[MAX_NUM_ARGS]) {
301  FileArgFactory args(file);
302  lAddArgsFromFactory(args, argc, argv);
303 }
304 
305 /** Parse a string for arguments and add them to the argc/argv passed as parameters */
306 static void lAddArgsFromString(const char *string, int &argc, char *argv[MAX_NUM_ARGS]) {
307  StringArgFactory args(string);
308  lAddArgsFromFactory(args, argc, argv);
309 }
310 
311 /** Add a single argument to the argc/argv passed as parameters. If the argument is of the
312  * form @<filename> and <filename> exists and is readable, the arguments in the file will be
313  * inserted into argc/argv in place of the original argument.
314  */
315 static void lAddSingleArg(char *arg, int &argc, char *argv[MAX_NUM_ARGS]) {
316  if (arg[0] == '@') {
317  char *filename = &arg[1];
318  FILE *file = fopen(filename, "r");
319  if (file != NULL) {
320  lAddArgsFromFile(file, argc, argv);
321  fclose(file);
322  arg = NULL;
323  }
324  }
325  if (arg != NULL) {
326  if (argc >= MAX_NUM_ARGS) {
327  fprintf(stderr, "More than %d arguments have been specified - aborting\n", MAX_NUM_ARGS);
328  exit(EXIT_FAILURE);
329  }
330  // printf("Arg %d: %s\n", argc, arg);
331  argv[argc++] = arg;
332  }
333 }
334 
335 /** We take arguments from both the command line as well as from the
336  * ISPC_ARGS environment variable - and each of these can include a file containing
337  * additional arguments using @<filename>. This function returns a new set of
338  * arguments representing the ones from all these sources merged together.
339  */
340 static void lGetAllArgs(int Argc, char *Argv[], int &argc, char *argv[MAX_NUM_ARGS]) {
341  argc = 0;
342 
343  // Copy over the command line arguments (passed in)
344  for (int i = 0; i < Argc; ++i)
345  lAddSingleArg(Argv[i], argc, argv);
346 
347  // See if we have any set via the environment variable
348  const char *env = getenv("ISPC_ARGS");
349  if (env)
350  lAddArgsFromString(env, argc, argv);
351 }
352 
353 static void lSignal(void *) { FATAL("Unhandled signal sent to process; terminating."); }
354 
355 static int ParsingPhaseName(char *stage) {
356  if (strncmp(stage, "first", 5) == 0) {
357  return 0;
358  } else if (strncmp(stage, "last", 4) == 0) {
359  return LAST_OPT_NUMBER;
360  } else {
361  int t = atoi(stage);
362  if (t < 0 || t > LAST_OPT_NUMBER) {
363  fprintf(stderr, "Phases must be from 0 to %d. %s is incorrect.\n", LAST_OPT_NUMBER, stage);
364  exit(0);
365  } else {
366  return t;
367  }
368  }
369 }
370 
371 static std::set<int> ParsingPhases(char *stages) {
372  std::set<int> phases;
373  /* ensure the string is NUL terminated */
374  stages[sizeof(stages) - 1] = '\0';
375  int begin = ParsingPhaseName(stages);
376  int end = begin;
377 
378  for (unsigned i = 0; i < strlen(stages); i++) {
379  if ((stages[i] == ',') || (i == strlen(stages) - 1)) {
380  for (int j = begin; j < end + 1; j++) {
381  phases.insert(j);
382  }
383  begin = ParsingPhaseName(stages + i + 1);
384  end = begin;
385  } else if (stages[i] == ':') {
386  end = ParsingPhaseName(stages + i + 1);
387  }
388  }
389  return phases;
390 }
391 
392 static void lParseInclude(const char *path) {
393 #ifdef ISPC_IS_WINDOWS
394  char delim = ';';
395 #else
396  char delim = ':';
397 #endif
398  size_t pos = 0, pos_end;
399  std::string str_path(path);
400  do {
401  pos_end = str_path.find(delim, pos);
402  size_t len = (pos_end == std::string::npos) ?
403  // Not found, copy till end of the string.
404  std::string::npos
405  :
406  // Copy [pos, pos_end).
407  (pos_end - pos);
408  std::string s = str_path.substr(pos, len);
409  g->includePath.push_back(s);
410  pos = pos_end + 1;
411  } while (pos_end != std::string::npos);
412 }
413 
414 int main(int Argc, char *Argv[]) {
415  int argc;
416  char *argv[MAX_NUM_ARGS];
417  lGetAllArgs(Argc, Argv, argc, argv);
418 
419  llvm::sys::AddSignalHandler(lSignal, NULL);
420 
421  // initialize available LLVM targets
422 #ifndef __arm__
423  // FIXME: LLVM build on ARM doesn't build the x86 targets by default.
424  // It's not clear that anyone's going to want to generate x86 from an
425  // ARM host, though...
426  LLVMInitializeX86TargetInfo();
427  LLVMInitializeX86Target();
428  LLVMInitializeX86AsmPrinter();
429  LLVMInitializeX86AsmParser();
430  LLVMInitializeX86Disassembler();
431  LLVMInitializeX86TargetMC();
432 #endif // !__ARM__
433 
434 #ifdef ISPC_ARM_ENABLED
435  // Generating ARM from x86 is more likely to be useful, though.
436  LLVMInitializeARMTargetInfo();
437  LLVMInitializeARMTarget();
438  LLVMInitializeARMAsmPrinter();
439  LLVMInitializeARMAsmParser();
440  LLVMInitializeARMDisassembler();
441  LLVMInitializeARMTargetMC();
442 #endif
443 
444 #ifdef ISPC_NVPTX_ENABLED
445  LLVMInitializeNVPTXTargetInfo();
446  LLVMInitializeNVPTXTarget();
447  LLVMInitializeNVPTXAsmPrinter();
448  LLVMInitializeNVPTXTargetMC();
449 #endif /* ISPC_NVPTX_ENABLED */
450 
451  char *file = NULL;
452  const char *headerFileName = NULL;
453  const char *outFileName = NULL;
454  const char *includeFileName = NULL;
455  const char *depsFileName = NULL;
456  const char *depsTargetName = NULL;
457  const char *hostStubFileName = NULL;
458  const char *devStubFileName = NULL;
459  // Initiailize globals early so that we can set various option values
460  // as we're parsing below
461  g = new Globals;
462 
465  const char *arch = NULL, *cpu = NULL, *target = NULL, *intelAsmSyntax = NULL;
466 
467  for (int i = 1; i < argc; ++i) {
468  if (!strcmp(argv[i], "--help"))
469  usage(0);
470  if (!strcmp(argv[i], "--help-dev"))
471  devUsage(0);
472  else if (!strncmp(argv[i], "-D", 2))
473  g->cppArgs.push_back(argv[i]);
474  else if (!strncmp(argv[i], "--addressing=", 13)) {
475  if (atoi(argv[i] + 13) == 64)
476  // FIXME: this doesn't make sense on 32 bit platform.
477  g->opt.force32BitAddressing = false;
478  else if (atoi(argv[i] + 13) == 32)
479  g->opt.force32BitAddressing = true;
480  else {
481  fprintf(stderr,
482  "Addressing width \"%s\" invalid--only 32 and "
483  "64 are allowed.\n",
484  argv[i] + 13);
485  usage(1);
486  }
487  } else if (!strncmp(argv[i], "--arch=", 7))
488  arch = argv[i] + 7;
489  else if (!strncmp(argv[i], "--x86-asm-syntax=", 17)) {
490  intelAsmSyntax = argv[i] + 17;
491  if (!((std::string(intelAsmSyntax) == "intel") || (std::string(intelAsmSyntax) == "att"))) {
492  intelAsmSyntax = NULL;
493  fprintf(stderr,
494  "Invalid value for --x86-asm-syntax: \"%s\" -- "
495  "only intel and att are allowed.\n",
496  argv[i] + 17);
497  }
498  } else if (!strncmp(argv[i], "--cpu=", 6))
499  cpu = argv[i] + 6;
500  else if (!strcmp(argv[i], "--fast-math")) {
501  fprintf(stderr, "--fast-math option has been renamed to --opt=fast-math!\n");
502  usage(1);
503  } else if (!strcmp(argv[i], "--fast-masked-vload")) {
504  fprintf(stderr, "--fast-masked-vload option has been renamed to "
505  "--opt=fast-masked-vload!\n");
506  usage(1);
507  } else if (!strcmp(argv[i], "--debug"))
508  g->debugPrint = true;
509 #ifdef ISPC_IS_WINDOWS
510  else if (!strcmp(argv[i], "--dllexport"))
511  g->dllExport = true;
512 #endif
513 #if ISPC_LLVM_VERSION >= ISPC_LLVM_3_5
514  else if (!strncmp(argv[i], "--dwarf-version=", 16)) {
515  int val = atoi(argv[i] + 16);
516  if (2 <= val && val <= 4) {
517  g->generateDebuggingSymbols = true;
518  g->generateDWARFVersion = val;
519  } else {
520  fprintf(stderr,
521  "Invalid value for DWARF version: \"%s\" -- "
522  "only 2, 3 and 4 are allowed.\n",
523  argv[i] + 16);
524  usage(1);
525  }
526  }
527 #endif
528  else if (!strcmp(argv[i], "--print-target"))
529  g->printTarget = true;
530  else if (!strcmp(argv[i], "--no-omit-frame-pointer"))
531  g->NoOmitFramePointer = true;
532  else if (!strcmp(argv[i], "--instrument"))
533  g->emitInstrumentation = true;
534  else if (!strcmp(argv[i], "--no-pragma-once"))
535  g->noPragmaOnce = true;
536  else if (!strcmp(argv[i], "-g")) {
537  g->generateDebuggingSymbols = true;
538  } else if (!strcmp(argv[i], "--emit-asm"))
539  ot = Module::Asm;
540  else if (!strcmp(argv[i], "--emit-c++"))
541  ot = Module::CXX;
542  else if (!strcmp(argv[i], "--emit-llvm"))
543  ot = Module::Bitcode;
544  else if (!strcmp(argv[i], "--emit-obj"))
545  ot = Module::Object;
546  else if (!strcmp(argv[i], "-I")) {
547  if (++i == argc) {
548  fprintf(stderr, "No path specified after -I option.\n");
549  usage(1);
550  }
551  lParseInclude(argv[i]);
552  } else if (!strncmp(argv[i], "-I", 2))
553  lParseInclude(argv[i] + 2);
554  else if (!strcmp(argv[i], "--fuzz-test"))
555  g->enableFuzzTest = true;
556  else if (!strncmp(argv[i], "--fuzz-seed=", 12))
557  g->fuzzTestSeed = atoi(argv[i] + 12);
558  else if (!strcmp(argv[i], "--target")) {
559  // FIXME: should remove this way of specifying the target...
560  if (++i == argc) {
561  fprintf(stderr, "No target specified after --target option.\n");
562  usage(1);
563  }
564  target = argv[i];
565  } else if (!strncmp(argv[i], "--target=", 9))
566  target = argv[i] + 9;
567  else if (!strncmp(argv[i], "--math-lib=", 11)) {
568  const char *lib = argv[i] + 11;
569  if (!strcmp(lib, "default"))
571  else if (!strcmp(lib, "fast"))
573  else if (!strcmp(lib, "svml"))
575  else if (!strcmp(lib, "system"))
577  else {
578  fprintf(stderr, "Unknown --math-lib= option \"%s\".\n", lib);
579  usage(1);
580  }
581  } else if (!strncmp(argv[i], "--opt=", 6)) {
582  const char *opt = argv[i] + 6;
583  if (!strcmp(opt, "fast-math"))
584  g->opt.fastMath = true;
585  else if (!strcmp(opt, "fast-masked-vload"))
586  g->opt.fastMaskedVload = true;
587  else if (!strcmp(opt, "disable-assertions"))
588  g->opt.disableAsserts = true;
589  else if (!strcmp(opt, "disable-loop-unroll"))
590  g->opt.unrollLoops = false;
591  else if (!strcmp(opt, "disable-fma"))
592  g->opt.disableFMA = true;
593  else if (!strcmp(opt, "force-aligned-memory"))
594  g->opt.forceAlignedMemory = true;
595 
596  // These are only used for performance tests of specific
597  // optimizations
598  else if (!strcmp(opt, "disable-all-on-optimizations"))
600  else if (!strcmp(opt, "disable-coalescing"))
601  g->opt.disableCoalescing = true;
602  else if (!strcmp(opt, "disable-handle-pseudo-memory-ops"))
604  else if (!strcmp(opt, "disable-blended-masked-stores"))
606  else if (!strcmp(opt, "disable-coherent-control-flow"))
608  else if (!strcmp(opt, "disable-uniform-control-flow"))
610  else if (!strcmp(opt, "disable-gather-scatter-optimizations"))
612  else if (!strcmp(opt, "disable-blending-removal"))
614  else if (!strcmp(opt, "disable-gather-scatter-flattening"))
616  else if (!strcmp(opt, "disable-uniform-memory-optimizations"))
618  else {
619  fprintf(stderr, "Unknown --opt= option \"%s\".\n", opt);
620  usage(1);
621  }
622  } else if (!strncmp(argv[i], "--force-alignment=", 18)) {
623  g->forceAlignment = atoi(argv[i] + 18);
624  } else if (!strcmp(argv[i], "--woff") || !strcmp(argv[i], "-woff")) {
625  g->disableWarnings = true;
626  g->emitPerfWarnings = false;
627  } else if (!strcmp(argv[i], "--werror"))
628  g->warningsAsErrors = true;
629  else if (!strcmp(argv[i], "--nowrap"))
630  g->disableLineWrap = true;
631  else if (!strcmp(argv[i], "--wno-perf") || !strcmp(argv[i], "-wno-perf"))
632  g->emitPerfWarnings = false;
633  else if (!strcmp(argv[i], "-o")) {
634  if (++i == argc) {
635  fprintf(stderr, "No output file specified after -o option.\n");
636  usage(1);
637  }
638  outFileName = argv[i];
639  } else if (!strncmp(argv[i], "--outfile=", 10))
640  outFileName = argv[i] + strlen("--outfile=");
641  else if (!strcmp(argv[i], "-h")) {
642  if (++i == argc) {
643  fprintf(stderr, "No header file name specified after -h option.\n");
644  usage(1);
645  }
646  headerFileName = argv[i];
647  } else if (!strncmp(argv[i], "--header-outfile=", 17)) {
648  headerFileName = argv[i] + strlen("--header-outfile=");
649  } else if (!strncmp(argv[i], "--c++-include-file=", 19)) {
650  includeFileName = argv[i] + strlen("--c++-include-file=");
651  } else if (!strcmp(argv[i], "-O0")) {
652  g->opt.level = 0;
653  g->codegenOptLevel = Globals::CodegenOptLevel::None;
654  } else if (!strcmp(argv[i], "-O") || !strcmp(argv[i], "-O1") || !strcmp(argv[i], "-O2") ||
655  !strcmp(argv[i], "-O3")) {
656  g->opt.level = 1;
657  g->codegenOptLevel = Globals::CodegenOptLevel::Aggressive;
658  if (!strcmp(argv[i], "-O1"))
660  } else if (!strcmp(argv[i], "-"))
661  ;
662  else if (!strcmp(argv[i], "--nostdlib"))
663  g->includeStdlib = false;
664  else if (!strcmp(argv[i], "--nocpp"))
665  g->runCPP = false;
666 #ifndef ISPC_IS_WINDOWS
667  else if (!strcmp(argv[i], "--pic"))
668  flags |= Module::GeneratePIC;
669  else if (!strcmp(argv[i], "--colored-output"))
670  g->forceColoredOutput = true;
671 #endif // !ISPC_IS_WINDOWS
672  else if (!strcmp(argv[i], "--quiet"))
673  g->quiet = true;
674  else if (!strcmp(argv[i], "--yydebug")) {
675  extern int yydebug;
676  yydebug = 1;
677  } else if (!strcmp(argv[i], "-MMM")) {
678  if (++i == argc) {
679  fprintf(stderr, "No output file name specified after -MMM option.\n");
680  usage(1);
681  }
682  depsFileName = argv[i];
683  flags |= Module::GenerateFlatDeps;
684  } else if (!strcmp(argv[i], "-M")) {
686  } else if (!strcmp(argv[i], "-MF")) {
687  depsFileName = nullptr;
688  if (++i == argc) {
689  fprintf(stderr, "No output file name specified after -MF option.\n");
690  usage(1);
691  }
692  depsFileName = argv[i];
693  } else if (!strcmp(argv[i], "-MT")) {
694  depsTargetName = nullptr;
695  if (++i == argc) {
696  fprintf(stderr, "No target name specified after -MT option.\n");
697  usage(1);
698  }
699  depsTargetName = argv[i];
700  } else if (!strcmp(argv[i], "--dev-stub")) {
701  if (++i == argc) {
702  fprintf(stderr, "No output file name specified after --dev-stub option.\n");
703  usage(1);
704  }
705  devStubFileName = argv[i];
706  } else if (!strcmp(argv[i], "--host-stub")) {
707  if (++i == argc) {
708  fprintf(stderr, "No output file name specified after --host-stub option.\n");
709  usage(1);
710  }
711  hostStubFileName = argv[i];
712  }
713 #ifndef ISPC_NO_DUMPS
714  else if (strncmp(argv[i], "--debug-phase=", 14) == 0) {
715  fprintf(stderr, "WARNING: Adding debug phases may change the way PassManager"
716  "handles the phases and it may possibly make some bugs go"
717  "away or introduce the new ones.\n");
718  g->debug_stages = ParsingPhases(argv[i] + strlen("--debug-phase="));
719  }
720 #endif
721 
722 #if ISPC_LLVM_VERSION == ISPC_LLVM_3_4 || ISPC_LLVM_VERSION == ISPC_LLVM_3_5 // 3.4, 3.5
723  else if (strncmp(argv[i], "--debug-ir=", 11) == 0) {
724  g->debugIR = ParsingPhaseName(argv[i] + strlen("--debug-ir="));
725  }
726 #endif
727  else if (strncmp(argv[i], "--off-phase=", 12) == 0) {
728  g->off_stages = ParsingPhases(argv[i] + strlen("--off-phase="));
729  } else if (!strcmp(argv[i], "-v") || !strcmp(argv[i], "--version")) {
730  lPrintVersion();
731  return 0;
732  } else if (argv[i][0] == '-') {
733  fprintf(stderr, "Unknown option \"%s\".\n", argv[i]);
734  usage(1);
735  } else {
736  if (file != NULL) {
737  fprintf(stderr,
738  "Multiple input files specified on command "
739  "line: \"%s\" and \"%s\".\n",
740  file, argv[i]);
741  usage(1);
742  } else
743  file = argv[i];
744  }
745  }
746 
747  if (g->enableFuzzTest) {
748  if (g->fuzzTestSeed == -1) {
749 #ifdef ISPC_IS_WINDOWS
750  int seed = (unsigned)time(NULL);
751 #else
752  int seed = getpid();
753 #endif
754  g->fuzzTestSeed = seed;
755  Warning(SourcePos(), "Using seed %d for fuzz testing", g->fuzzTestSeed);
756  }
757 #ifdef ISPC_IS_WINDOWS
758  srand(g->fuzzTestSeed);
759 #else
760  srand48(g->fuzzTestSeed);
761 #endif
762  }
763 
764  if (depsFileName != NULL)
765  flags &= ~Module::OutputDepsToStdout;
766 
767  if (depsFileName != NULL && 0 == (flags & (Module::GenerateFlatDeps | Module::GenerateMakeRuleForDeps))) {
768  Warning(SourcePos(), "Dependency file name specified with -MF, but no "
769  "mode specified; did you forget to specify -M or -MMM? "
770  "No dependency output will be generated.");
771  depsFileName = NULL;
772  }
773 
776  Warning(SourcePos(), "Both -M and -MMM specified on the command line. "
777  "-MMM takes precedence.");
779  }
780 
781  if (outFileName == NULL && headerFileName == NULL &&
782  (depsFileName == NULL && 0 == (flags & Module::OutputDepsToStdout)) && hostStubFileName == NULL &&
783  devStubFileName == NULL)
784  Warning(SourcePos(), "No output file or header file name specified. "
785  "Program will be compiled and warnings/errors will "
786  "be issued, but no output will be generated.");
787 
788  if ((ot == Module::Asm) && (intelAsmSyntax != NULL)) {
789  std::vector<const char *> Args(3);
790  Args[0] = "ispc (LLVM option parsing)";
791  Args[2] = nullptr;
792  if (std::string(intelAsmSyntax) == "intel")
793  Args[1] = "--x86-asm-syntax=intel";
794  else
795  Args[1] = "--x86-asm-syntax=att";
796  llvm::cl::ParseCommandLineOptions(2, Args.data());
797  }
798 
799  return Module::CompileAndOutput(file, arch, cpu, target, flags, ot, outFileName, headerFileName, includeFileName,
800  depsFileName, depsTargetName, hostStubFileName, devStubFileName);
801 }
bool disableFMA
Definition: ispc.h:453
Opt opt
Definition: ispc.h:535
bool disableWarnings
Definition: ispc.h:577
This structure collects together a number of global variables.
Definition: ispc.h:531
bool disableBlendedMaskedStores
Definition: ispc.h:480
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:2962
static void lSignal(void *)
Definition: main.cpp:353
bool forceColoredOutput
Definition: ispc.h:595
virtual char GetNextChar()=0
std::vector< std::string > includePath
Definition: ispc.h:644
bool emitPerfWarnings
Definition: ispc.h:588
bool warningsAsErrors
Definition: ispc.h:580
bool NoOmitFramePointer
Definition: ispc.h:564
static void lAddArgsFromFile(FILE *file, int &argc, char *argv[MAX_NUM_ARGS])
Definition: main.cpp:300
static void lAddSingleArg(char *arg, int &argc, char *argv[MAX_NUM_ARGS])
Definition: main.cpp:315
bool forceAlignedMemory
Definition: ispc.h:459
char * AllocateString(std::string string)
Definition: main.cpp:211
static void lGetAllArgs(int Argc, char *Argv[], int &argc, char *argv[MAX_NUM_ARGS])
Definition: main.cpp:340
int fuzzTestSeed
Definition: ispc.h:629
static const char * SupportedArchs()
Definition: ispc.cpp:1144
OutputType
Definition: module.h:91
static void devUsage(int ret)
Definition: main.cpp:176
bool disableLineWrap
Definition: ispc.h:584
bool disableCoalescing
Definition: ispc.h:520
virtual char GetNextChar()
Definition: main.cpp:271
ArgFactory()
Definition: main.cpp:224
bool includeStdlib
Definition: ispc.h:550
std::set< int > debug_stages
Definition: ispc.h:567
bool disableMaskAllOnOptimizations
Definition: ispc.h:464
int level
Definition: ispc.h:425
static void lAddArgsFromString(const char *string, int &argc, char *argv[MAX_NUM_ARGS])
Definition: main.cpp:306
static std::string SupportedCPUs()
Definition: ispc.cpp:1139
Globals * g
Definition: ispc.cpp:101
bool disableGatherScatterOptimizations
Definition: ispc.h:498
bool debugPrint
Definition: ispc.h:558
bool disableCoherentControlFlow
Definition: ispc.h:486
static void lPrintVersion()
Definition: main.cpp:68
bool enableFuzzTest
Definition: ispc.h:626
bool printTarget
Definition: ispc.h:561
Definition: module.h:56
void PrintWithWordBreaks(const char *buf, int indent, int columnWidth, FILE *out)
Definition: util.cpp:210
FILE * InputFile
Definition: main.cpp:251
int TerminalWidth()
Definition: util.cpp:80
const char * InputString
Definition: main.cpp:269
bool runCPP
Definition: ispc.h:554
CodegenOptLevel codegenOptLevel
Definition: ispc.h:546
bool emitInstrumentation
Definition: ispc.h:601
bool unrollLoops
Definition: ispc.h:439
Representation of a range of positions in a source file.
Definition: ispc.h:129
bool disableUniformMemoryOptimizations
Definition: ispc.h:516
bool generateDebuggingSymbols
Definition: ispc.h:607
bool fastMath
Definition: ispc.h:429
static void lAddArgsFromFactory(ArgFactory &Args, int &argc, char *argv[MAX_NUM_ARGS])
Definition: main.cpp:290
static void lParseInclude(const char *path)
Definition: main.cpp:392
bool fastMaskedVload
Definition: ispc.h:435
bool disableHandlePseudoMemoryOps
Definition: ispc.h:470
bool force32BitAddressing
Definition: ispc.h:445
bool dllExport
Definition: ispc.h:651
void Warning(SourcePos p, const char *format,...) PRINTF_FUNC
Definition: util.cpp:375
int main(int Argc, char *Argv[])
Definition: main.cpp:414
#define FATAL(message)
Definition: util.h:112
StringArgFactory(const char *string)
Definition: main.cpp:281
MathLib mathLib
Definition: ispc.h:542
bool disableUniformControlFlow
Definition: ispc.h:492
bool disableMaskedStoreToStore
Definition: ispc.h:504
OutputFlags
Definition: module.h:104
char * GetNextArg()
Definition: main.cpp:226
int forceAlignment
Definition: ispc.h:648
static int ParsingPhaseName(char *stage)
Definition: main.cpp:355
bool quiet
Definition: ispc.h:591
std::set< int > off_stages
Definition: ispc.h:574
bool noPragmaOnce
Definition: ispc.h:603
std::vector< std::string > cppArgs
Definition: ispc.h:640
virtual char GetNextChar()
Definition: main.cpp:253
static std::set< int > ParsingPhases(char *stages)
Definition: main.cpp:371
Declaration of the Module class, which is the ispc-side representation of the results of compiling a ...
static const char * SupportedTargets()
Definition: ispc.cpp:1152
#define LAST_OPT_NUMBER
Definition: ispc.h:72
Main ispc.header file. Defines Target, Globals and Opt classes.
static void usage(int ret)
Definition: main.cpp:88
bool disableAsserts
Definition: ispc.h:449
#define MAX_NUM_ARGS
Definition: main.cpp:66
File with declarations for classes related to type representation.
bool disableGatherScatterFlattening
Definition: ispc.h:510
FileArgFactory(FILE *file)
Definition: main.cpp:263
int debugIR
Definition: ispc.h:571