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