Intel SPMD Program Compiler  1.10.0
util.cpp
Go to the documentation of this file.
1 /*
2  Copyright (c) 2010-2018, 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 util.cpp
35  @brief Various small utility routines.
36 */
37 
38 #include "util.h"
39 #include "module.h"
40 #ifdef ISPC_IS_WINDOWS
41 #include <shlwapi.h>
42 #ifdef __MINGW32__
43 #include <malloc.h> // for alloca()
44 #endif
45 #else
46 #include <alloca.h>
47 #include <unistd.h>
48 #endif
49 #include <stdio.h>
50 
51 #include <stdio.h>
52 #include <ctype.h>
53 #include <stdarg.h>
54 #include <stdlib.h>
55 #include <string.h>
56 #ifdef ISPC_IS_WINDOWS
57 #include <io.h>
58 #include <direct.h>
59 #include <windows.h>
60 #else
61 #include <sys/ioctl.h>
62 #include <unistd.h>
63 #include <errno.h>
64 #endif // ISPC_IS_WINDOWS
65 #include <set>
66 #include <algorithm>
67 
68 #if ISPC_LLVM_VERSION == ISPC_LLVM_3_2
69  #include <llvm/DataLayout.h>
70 #else // LLVM 3.3+
71  #include <llvm/IR/DataLayout.h>
72 #endif
73 
74 /** Returns the width of the terminal where the compiler is running.
75  Finding this out may fail in a variety of reasonable situations (piping
76  compiler output to 'less', redirecting output to a file, running the
77  compiler under a debuffer; in this case, just return a reasonable
78  default.
79  */
80 int
82  if (g->disableLineWrap)
83  return 1<<30;
84 
85 #if defined(ISPC_IS_WINDOWS)
86  HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE);
87  if (h == INVALID_HANDLE_VALUE || h == NULL)
88  return 80;
89  CONSOLE_SCREEN_BUFFER_INFO bufferInfo = { {0} };
90  GetConsoleScreenBufferInfo(h, &bufferInfo);
91  return bufferInfo.dwSize.X;
92 #else
93  struct winsize w;
94  if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &w) < 0)
95  return 80;
96  return w.ws_col;
97 #endif // ISPC_IS_WINDOWS
98 }
99 
100 
101 static bool
103  static bool r = (getenv("TERM") != NULL &&
104  strcmp(getenv("TERM"), "dumb") != 0);
105 #ifndef ISPC_IS_WINDOWS
106  r &= isatty(2);
107 #endif // !ISPC_IS_WINDOWS
108  r |= g->forceColoredOutput;
109  return r;
110 }
111 
112 
113 static const char *
115  if (lHaveANSIColors())
116  return "\033[1m";
117  else
118  return "";
119 }
120 
121 
122 static const char *
124  if (lHaveANSIColors())
125  return "\033[31m";
126  else
127  return "";
128 }
129 
130 
131 static const char *
133  if (lHaveANSIColors())
134  return "\033[34m";
135  else
136  return "";
137 }
138 
139 
140 static const char *
142  if (lHaveANSIColors())
143  return "\033[0m";
144  else
145  return "";
146 }
147 
148 /** Given a pointer into a string, find the end of the current word and
149  return a pointer to its last character.
150 */
151 static const char *
152 lFindWordEnd(const char *buf) {
153  while (*buf != '\0' && !isspace(*buf))
154  ++buf;
155  return buf;
156 }
157 
158 /** When printing error messages, we sometimes want to include the source
159  file line for context. This function print the line(s) of the file
160  corresponding to the provided SourcePos and underlines the range of the
161  SourcePos with '^' symbols.
162 */
163 static void
165  if (p.first_line == 0)
166  return;
167 
168  FILE *f = fopen(p.name, "r");
169  if (!f)
170  return;
171 
172  int c, curLine = 1;
173  while ((c = fgetc(f)) != EOF) {
174  // Don't print more than three lines of context. (More than that,
175  // and we're probably doing the wrong thing...)
176  if (curLine >= std::max(p.first_line, p.last_line-2) &&
177  curLine <= p.last_line)
178  fputc(c, stderr);
179  if (c == '\n')
180  ++curLine;
181  if (curLine > p.last_line)
182  break;
183  }
184 
185  int i = 1;
186  for (; i < p.first_column; ++i)
187  fputc(' ', stderr);
188  fputc('^', stderr);
189  ++i;
190  for (; i < p.last_column; ++i)
191  fputc('^', stderr);
192  fputc('\n', stderr);
193  fputc('\n', stderr);
194 
195  fclose(f);
196 }
197 
198 
199 /** Counts the number of characters into the buf at which the numColons
200  colon character is found. Skips over ANSI escape sequences and doesn't
201  include their characters in the final count.
202  */
203 static int
204 lFindIndent(int numColons, const char *buf) {
205  int indent = 0;
206  while (*buf != '\0') {
207  if (*buf == '\033') {
208  while (*buf != '\0' && *buf != 'm')
209  ++buf;
210  if (*buf == 'm')
211  ++buf;
212  }
213  else {
214  if (*buf == ':') {
215  if (--numColons == 0)
216  break;
217  }
218  ++indent;
219  ++buf;
220  }
221  }
222  return indent + 2;
223 }
224 
225 
226 /** Print the given string to the given FILE, assuming the given output
227  column width. Break words as needed to avoid words spilling past the
228  last column. */
229 void
230 PrintWithWordBreaks(const char *buf, int indent, int columnWidth, FILE *out) {
231 #ifdef ISPC_IS_WINDOWS
232  fputs(buf, out);
233  fputs("\n", out);
234 #else
235  int column = 0;
236  int width = std::max(40, columnWidth - 2);
237 
238  // Collect everything into a string and print it all at once at the end
239  // -> try to avoid troubles with mangled error messages with
240  // multi-threaded builds.
241  std::string outStr;
242 
243  const char *msgPos = buf;
244  while (true) {
245  if (*msgPos == '\033') {
246  // handle ANSI color escape: copy it to the output buffer
247  // without charging for the characters it uses
248  do {
249  outStr.push_back(*msgPos++);
250  } while (*msgPos != '\0' && *msgPos != 'm');
251  continue;
252  }
253  else if (*msgPos == '\n') {
254  // Handle newlines cleanly
255  column = indent;
256  outStr.push_back('\n');
257  for (int i = 0; i < indent; ++i)
258  outStr.push_back(' ');
259  // Respect spaces after newlines
260  ++msgPos;
261  while (*msgPos == ' ') {
262  outStr.push_back(' ');
263  ++msgPos;
264  }
265  continue;
266  }
267 
268  while (*msgPos != '\0' && isspace(*msgPos))
269  ++msgPos;
270  if (*msgPos == '\0')
271  break;
272 
273  const char *wordEnd = lFindWordEnd(msgPos);
274  if (column > indent && column + wordEnd - msgPos > width) {
275  // This word would overflow, so start a new line
276  column = indent;
277  outStr.push_back('\n');
278  // Indent to the same column as the ":" at the start of the
279  // message.
280  for (int i = 0; i < indent; ++i)
281  outStr.push_back(' ');
282  }
283 
284  // Finally go and copy the word
285  while (msgPos != wordEnd) {
286  outStr.push_back(*msgPos++);
287  ++column;
288  }
289  outStr.push_back(' ');
290  ++column;
291  }
292  outStr.push_back('\n');
293  fputs(outStr.c_str(), out);
294 #endif
295 }
296 
297 
298 #ifdef ISPC_IS_WINDOWS
299 // we cover for the lack vasprintf and asprintf on windows (also covers mingw)
300 int
301 vasprintf(char **sptr, const char *fmt, va_list argv)
302 {
303  int wanted = vsnprintf(*sptr = NULL, 0, fmt, argv);
304  if((wanted < 0) || ((*sptr = (char*)malloc( 1 + wanted )) == NULL))
305  return -1;
306 
307  return vsprintf(*sptr, fmt, argv);
308 }
309 
310 
311 int
312 asprintf(char **sptr, const char *fmt, ...)
313 {
314  int retval;
315  va_list argv;
316  va_start(argv, fmt);
317  retval = vasprintf(sptr, fmt, argv);
318  va_end(argv);
319  return retval;
320 }
321 #endif
322 
323 
324 /** Helper function for Error(), Warning(), etc.
325 
326  @param type The type of message being printed (e.g. "Warning")
327  @param p Position in source file that is connected to the message
328  being printed
329  @param fmt printf()-style format string
330  @param args Arguments with values for format string % entries
331 */
332 static void
333 lPrint(const char *type, bool isError, SourcePos p, const char *fmt,
334  va_list args) {
335  char *errorBuf, *formattedBuf;
336  if (vasprintf(&errorBuf, fmt, args) == -1) {
337  fprintf(stderr, "vasprintf() unable to allocate memory!\n");
338  abort();
339  }
340 
341  int indent = 0;
342  if (p.first_line == 0) {
343  // We don't have a valid SourcePos, so create a message without it
344  if (asprintf(&formattedBuf, "%s%s%s%s%s: %s%s", lStartBold(),
345  isError ? lStartRed() : lStartBlue(), type,
346  lResetColor(), lStartBold(), errorBuf,
347  lResetColor()) == -1) {
348  fprintf(stderr, "asprintf() unable to allocate memory!\n");
349  exit(1);
350  }
351  indent = lFindIndent(1, formattedBuf);
352  }
353  else {
354  // Create an error message that includes the file and line number
355  if (asprintf(&formattedBuf, "%s%s:%d:%d: %s%s%s%s: %s%s",
357  isError ? lStartRed() : lStartBlue(), type,
358  lResetColor(), lStartBold(), errorBuf,
359  lResetColor()) == -1) {
360  fprintf(stderr, "asprintf() unable to allocate memory!\n");
361  exit(1);
362  }
363  indent = lFindIndent(3, formattedBuf);
364  }
365  // Don't indent too much with long filenames
366  indent = std::min(indent, 8);
367 
368  // Now that we've done all that work, see if we've already printed the
369  // exact same error message. If so, return, so we don't redundantly
370  // print it and annoy the user.
371  static std::set<std::string> printed;
372  if (printed.find(formattedBuf) != printed.end())
373  return;
374  printed.insert(formattedBuf);
375 
376  PrintWithWordBreaks(formattedBuf, indent, TerminalWidth(), stderr);
378 
379  free(errorBuf);
380  free(formattedBuf);
381 }
382 
383 
384 void
385 Error(SourcePos p, const char *fmt, ...) {
386  if (m != NULL) ++m->errorCount;
387  if (g->quiet)
388  return;
389 
390  va_list args;
391  va_start(args, fmt);
392  lPrint("Error", true, p, fmt, args);
393  va_end(args);
394 }
395 
396 
397 void
398 Debug(SourcePos p, const char *fmt, ...) {
399  if (!g->debugPrint || g->quiet)
400  return;
401 
402  va_list args;
403  va_start(args, fmt);
404  lPrint("Debug", false, p, fmt, args);
405  va_end(args);
406 }
407 
408 
409 void
410 Warning(SourcePos p, const char *fmt, ...) {
411 
412  std::map<std::pair<int, std::string>, bool>::iterator turnOffWarnings_it =
413  g->turnOffWarnings.find(std::pair<int, std::string>(p.last_line, std::string(p.name)));
414  if ((turnOffWarnings_it != g->turnOffWarnings.end()) && (turnOffWarnings_it->second == false))
415  return;
416 
417  if (g->warningsAsErrors && m != NULL)
418  ++m->errorCount;
419 
420  if (g->disableWarnings || g->quiet)
421  return;
422 
423  va_list args;
424  va_start(args, fmt);
425  lPrint(g->warningsAsErrors ? "Error" : "Warning", g->warningsAsErrors,
426  p, fmt, args);
427  va_end(args);
428 }
429 
430 
431 void
432 PerformanceWarning(SourcePos p, const char *fmt, ...) {
433  std::string stdlibFile = "stdlib.ispc";
434  std::string sourcePosName = p.name;
435  if (!g->emitPerfWarnings ||
436  (sourcePosName.length() >= stdlibFile.length() &&
437  sourcePosName.compare(sourcePosName.length() - stdlibFile.length(), stdlibFile.length(), stdlibFile) == 0) ||
438  g->quiet)
439  return;
440 
441  std::map<std::pair<int, std::string>, bool>::iterator turnOffWarnings_it =
442  g->turnOffWarnings.find(std::pair<int, std::string>(p.last_line, p.name));
443  if (turnOffWarnings_it != g->turnOffWarnings.end())
444  return;
445 
446  if (g->warningsAsErrors && m != NULL)
447  ++m->errorCount;
448 
449  va_list args;
450  va_start(args, fmt);
451  lPrint("Performance Warning", false, p, fmt, args);
452  va_end(args);
453 }
454 
455 
456 static void
458  static bool printed = false;
459  if (printed)
460  return;
461 
462  printed = true;
463  fprintf(stderr, "***\n"
464  "*** Please file a bug report at https://github.com/ispc/ispc/issues\n"
465  "*** (Including as much information as you can about how to "
466  "reproduce this error).\n"
467  "*** You have apparently encountered a bug in the compiler that we'd "
468  "like to fix!\n***\n");
469 }
470 
471 
472 void
473 FatalError(const char *file, int line, const char *message) {
474  fprintf(stderr, "%s(%d): FATAL ERROR: %s\n", file, line, message);
475  lPrintBugText();
476  abort();
477 }
478 
479 
480 void
481 DoAssert(const char *file, int line, const char *expr) {
482  fprintf(stderr, "%s:%u: Assertion failed: \"%s\".\n", file, line, expr);
483  lPrintBugText();
484  abort();
485 }
486 
487 
488 void
489 DoAssertPos(SourcePos pos, const char *file, int line, const char *expr) {
490  Error(pos, "Assertion failed (%s:%u): \"%s\".", file, line, expr);
491  lPrintBugText();
492  abort();
493 }
494 
495 
496 ///////////////////////////////////////////////////////////////////////////
497 
498 // http://en.wikipedia.org/wiki/Levenshtein_distance
499 int
500 StringEditDistance(const std::string &str1, const std::string &str2, int maxDist) {
501  // Small hack: don't return 0 if the strings are the same; if we've
502  // gotten here, there's been a parsing error, and suggesting the same
503  // string isn't going to actually help things.
504  if (str1 == str2)
505  return maxDist;
506 
507  int n1 = (int)str1.size(), n2 = (int)str2.size();
508  int nmax = std::max(n1, n2);
509 
510  int *current = (int *)alloca((nmax+1) * sizeof(int));
511  int *previous = (int *)alloca((nmax+1) * sizeof(int));
512 
513  for (int i = 0; i <= n2; ++i)
514  previous[i] = i;
515 
516  for (int y = 1; y <= n1; ++y) {
517  current[0] = y;
518  int rowBest = y;
519 
520  for (int x = 1; x <= n2; ++x) {
521  current[x] = std::min(previous[x-1] + (str1[y-1] == str2[x-1] ? 0 : 1),
522  std::min(current[x-1], previous[x])+1);
523  rowBest = std::min(rowBest, current[x]);
524  }
525 
526  if (maxDist != 0 && rowBest > maxDist)
527  return maxDist + 1;
528 
529  std::swap(current, previous);
530  }
531 
532  return previous[n2];
533 }
534 
535 
536 std::vector<std::string>
537 MatchStrings(const std::string &str, const std::vector<std::string> &options) {
538  if (str.size() == 0 || (str.size() == 1 && !isalpha(str[0])))
539  // don't even try...
540  return std::vector<std::string>();
541 
542  const int maxDelta = 2;
543  std::vector<std::string> matches[maxDelta+1];
544 
545  // For all of the options that are up to maxDelta edit distance, store
546  // them in the element of matches[] that corresponds to their edit
547  // distance.
548  for (int i = 0; i < (int)options.size(); ++i) {
549  int dist = StringEditDistance(str, options[i], maxDelta+1);
550  if (dist <= maxDelta)
551  matches[dist].push_back(options[i]);
552  }
553 
554  // And return the first one of them, if any, that has at least one
555  // match.
556  for (int i = 0; i <= maxDelta; ++i) {
557  if (matches[i].size())
558  return matches[i];
559  }
560  return std::vector<std::string>();
561 }
562 
563 
564 void
565 GetDirectoryAndFileName(const std::string &currentDirectory,
566  const std::string &relativeName,
567  std::string *directory, std::string *filename) {
568 #ifdef ISPC_IS_WINDOWS
569  char path[MAX_PATH];
570  const char *combPath = PathCombine(path, currentDirectory.c_str(),
571  relativeName.c_str());
572  Assert(combPath != NULL);
573  const char *filenamePtr = PathFindFileName(combPath);
574  *filename = filenamePtr;
575  *directory = std::string(combPath, filenamePtr - combPath);
576 #else
577  // We need a fully qualified path. First, see if the current file name
578  // is fully qualified itself--in that case, the current working
579  // directory isn't needed.
580  // @todo This probably needs to be smarter for Windows...
581  std::string fullPath;
582  if (relativeName[0] == '/')
583  fullPath = relativeName;
584  else {
585  fullPath = g->currentDirectory;
586  if (fullPath[fullPath.size()-1] != '/')
587  fullPath.push_back('/');
588  fullPath += relativeName;
589  }
590 
591  // now, we need to separate it into the base name and the directory
592  const char *fp = fullPath.c_str();
593  const char *basenameStart = strrchr(fp, '/');
594  Assert(basenameStart != NULL);
595  ++basenameStart;
596  Assert(basenameStart[0] != '\0');
597  *filename = basenameStart;
598  *directory = std::string(fp, basenameStart - fp);
599 #endif // ISPC_IS_WINDOWS
600 }
601 
602 static std::set<std::string> lGetStringArray(const std::string &str) {
603  std::set<std::string> result;
604 
605  Assert(str.find('-') != str.npos);
606 
607  size_t pos_prev = 0, pos;
608  do {
609  pos = str.find('-', pos_prev);
610  std::string substr = str.substr(pos_prev, pos-pos_prev);
611  result.insert(substr);
612  pos_prev = pos;
613  pos_prev++;
614  } while (pos != str.npos);
615 
616  return result;
617 }
618 
619 
620 bool
621 VerifyDataLayoutCompatibility(const std::string &module_dl,
622  const std::string &lib_dl) {
623  if (lib_dl.empty()) {
624  // This is the case for most of library pre-compiled .ll files.
625  return true;
626  }
627 
628  // Get "canonical" form. Instead of looking at "raw" DataLayout string, we
629  // look at the actual representation, as DataLayout class understands it.
630  // In the most cases there's no difference. But on x86 Windows (i386-pc-win32),
631  // clang generates a DataLayout string, which contains two definitions of f80,
632  // which contradic: f80:128:128 followed by f80:32:32. This is a bug, but
633  // correct thing to do is to interpret this exactly how LLVM would treat it,
634  // so we create a DataLayout class and take its string representation.
635 
636  llvm::DataLayout d1(module_dl);
637  llvm::DataLayout d2(lib_dl);
638 
639  std::string module_dl_canonic = d1.getStringRepresentation();
640  std::string lib_dl_canonic = d2.getStringRepresentation();
641 
642  // Break down DataLayout strings to separate type definitions.
643  std::set<std::string> module_dl_set = lGetStringArray(module_dl_canonic);
644  std::set<std::string> lib_dl_set = lGetStringArray(lib_dl_canonic);
645 
646  // For each element in library data layout, find matching module element.
647  // If no match is found, then we are in trouble and the library can't be used.
648  for (std::set<std::string>::iterator it = lib_dl_set.begin();
649  it != lib_dl_set.end(); ++it) {
650  // We use the simplest possible definition of "match", which is match exactly.
651  // Ideally it should be relaxed and for triples [p|i|v|f|a|s]<size>:<abi>:<pref>
652  // we should allow <pref> part (preferred alignment) to not match.
653  // But this seems to have no practical value at this point.
654  std::set<std::string>::iterator module_match =
655  std::find(module_dl_set.begin(), module_dl_set.end(), *it);
656  if (module_match == module_dl_set.end()) {
657  // No match for this piece of library DataLayout was found,
658  // return false.
659  return false;
660  }
661  // Remove matching piece from Module set.
662  module_dl_set.erase(module_match);
663  }
664 
665  // We allow extra types to be defined in the Module, but we should check
666  // that it's something that we expect. And we expect vectors and floats.
667  for (std::set<std::string>::iterator it = module_dl_set.begin();
668  it != module_dl_set.end(); ++it) {
669  if ((*it)[0] == 'v' || (*it)[0] == 'f') {
670  continue;
671  }
672  return false;
673  }
674 
675  return true;
676 }
677 
static const char * lStartBold()
Definition: util.cpp:114
static void lPrintBugText()
Definition: util.cpp:457
int last_column
Definition: ispc.h:145
bool disableWarnings
Definition: ispc.h:586
std::map< std::pair< int, std::string >, bool > turnOffWarnings
Definition: ispc.h:661
Module * m
Definition: ispc.cpp:101
int TerminalWidth()
Definition: util.cpp:81
int first_line
Definition: ispc.h:142
bool forceColoredOutput
Definition: ispc.h:604
bool emitPerfWarnings
Definition: ispc.h:597
bool warningsAsErrors
Definition: ispc.h:589
#define Assert(expr)
Definition: ispc.h:173
static const char * lStartRed()
Definition: util.cpp:123
bool disableLineWrap
Definition: ispc.h:593
std::vector< std::string > MatchStrings(const std::string &str, const std::vector< std::string > &options)
Definition: util.cpp:537
bool VerifyDataLayoutCompatibility(const std::string &module_dl, const std::string &lib_dl)
Definition: util.cpp:621
void FatalError(const char *file, int line, const char *message)
Definition: util.cpp:473
static const char * lResetColor()
Definition: util.cpp:141
Globals * g
Definition: ispc.cpp:100
void PerformanceWarning(SourcePos p, const char *fmt,...)
Definition: util.cpp:432
bool debugPrint
Definition: ispc.h:567
static void lPrintFileLineContext(SourcePos p)
Definition: util.cpp:164
void DoAssertPos(SourcePos pos, const char *file, int line, const char *expr)
Definition: util.cpp:489
char currentDirectory[1024]
Definition: ispc.h:643
void GetDirectoryAndFileName(const std::string &currentDirectory, const std::string &relativeName, std::string *directory, std::string *filename)
Definition: util.cpp:565
static const char * lStartBlue()
Definition: util.cpp:132
Representation of a range of positions in a source file.
Definition: ispc.h:137
static bool lHaveANSIColors()
Definition: util.cpp:102
const char * name
Definition: ispc.h:141
static const char * lFindWordEnd(const char *buf)
Definition: util.cpp:152
void Error(SourcePos p, const char *fmt,...)
Definition: util.cpp:385
int last_line
Definition: ispc.h:144
int first_column
Definition: ispc.h:143
int StringEditDistance(const std::string &str1, const std::string &str2, int maxDist)
Definition: util.cpp:500
static void lPrint(const char *type, bool isError, SourcePos p, const char *fmt, va_list args)
Definition: util.cpp:333
static int lFindIndent(int numColons, const char *buf)
Definition: util.cpp:204
void Debug(SourcePos p, const char *fmt,...)
Definition: util.cpp:398
void PrintWithWordBreaks(const char *buf, int indent, int columnWidth, FILE *out)
Definition: util.cpp:230
static std::set< std::string > lGetStringArray(const std::string &str)
Definition: util.cpp:602
bool quiet
Definition: ispc.h:600
Declaration of the Module class, which is the ispc-side representation of the results of compiling a ...
int errorCount
Definition: module.h:159
void Warning(SourcePos p, const char *fmt,...)
Definition: util.cpp:410
void DoAssert(const char *file, int line, const char *expr)
Definition: util.cpp:481