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