Intel SPMD Program Compiler  1.9.1
builtins.c
Go to the documentation of this file.
1 /*
2  Copyright (c) 2010-2013, 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 builtins-c.c
35  @brief Standard library function implementations written in C.
36 
37  This file provides C implementations of various functions that can be
38  called from ispc programs; in other words, this file is *not* linked
39  into the ispc compiler executable, but rather provides functions that
40  can be compiled into ispc programs.
41 
42  When the ispc compiler is built, this file is compiled with clang to
43  generate LLVM bitcode. This bitcode is later linked in to the program
44  being compiled by the DefineStdlib() function. The first way to access
45  definitions from this file is by asking for them name from the
46  llvm::Module's' symbol table (e.g. as the PrintStmt implementation does
47  with __do_print() below. Alternatively, if a function defined in this
48  file has a signature that can be mapped back to ispc types by the
49  lLLVMTypeToIspcType() function, then its declaration will be made
50  available to ispc programs at compile time automatically.
51  */
52 
53 #ifdef _MSC_VER
54 // We do want old school sprintf and don't want secure Microsoft extensions.
55 // And we also don't want warnings about it, so the define.
56 #define _CRT_SECURE_NO_WARNINGS
57 #else
58 // Some versions of glibc has "fortification" feature, which expands sprintf
59 // to __builtin___sprintf_chk(..., __builtin_object_size(...), ...).
60 // We don't want this kind of expansion, as we don't support these intrinsics.
61 #define _FORTIFY_SOURCE 0
62 #endif
63 
64 #ifndef _MSC_VER
65 #include <unistd.h>
66 #endif // !_MSC_VER
67 
68 #include <stdint.h>
69 #include <stdio.h>
70 #include <stdlib.h>
71 #include <stdarg.h>
72 #include <string.h>
73 
74 typedef int Bool;
75 
76 #define PRINT_BUF_SIZE 4096
77 
78 #define APPEND(str) \
79  do { \
80  int offset = bufp - &printString[0]; \
81  *bufp = '\0'; \
82  strncat(bufp, str, PRINT_BUF_SIZE-offset); \
83  bufp += strlen(str); \
84  if (bufp >= &printString[PRINT_BUF_SIZE]) \
85  goto done; \
86  } while (0) /* eat semicolon */
87 
88 
89 #define PRINT_SCALAR(fmt, type) \
90  sprintf(tmpBuf, fmt, *((type *)ptr)); \
91  APPEND(tmpBuf); \
92  break
93 
94 #define PRINT_VECTOR(fmt, type) \
95  *bufp++ = '['; \
96  if (bufp == &printString[PRINT_BUF_SIZE]) break; \
97  for (int i = 0; i < width; ++i) { \
98  /* only print the value if the current lane is executing */ \
99  if (mask & (1ull<<i)) \
100  sprintf(tmpBuf, fmt, ((type *)ptr)[i]); \
101  else \
102  sprintf(tmpBuf, "((" fmt "))", ((type *)ptr)[i]); \
103  APPEND(tmpBuf); \
104  *bufp++ = (i != width-1 ? ',' : ']'); \
105  } \
106  break
107 
108 /** This function is called by PrintStmt to do the work of printing values
109  from ispc programs. Note that the function signature here must match
110  the parameters that PrintStmt::EmitCode() generates.
111 
112  @param format Print format string
113  @param types Encoded types of the values being printed.
114  (See lEncodeType()).
115  @param width Vector width of the compilation target
116  @param mask Current lane mask when the print statemnt is called
117  @param args Array of pointers to the values to be printed
118  */
119 void __do_print(const char *format, const char *types, int width, uint64_t mask,
120  void **args) {
121  char printString[PRINT_BUF_SIZE+1]; // +1 for trailing NUL
122  char *bufp = &printString[0];
123  char tmpBuf[256];
124 
125  int argCount = 0;
126  while (*format && bufp < &printString[PRINT_BUF_SIZE]) {
127  // Format strings are just single percent signs.
128  if (*format != '%') {
129  *bufp++ = *format;
130  }
131  else {
132  if (*types) {
133  void *ptr = args[argCount++];
134  // Based on the encoding in the types string, cast the
135  // value appropriately and print it with a reasonable
136  // printf() formatting string.
137  switch (*types) {
138  case 'b': {
139  sprintf(tmpBuf, "%s", *((Bool *)ptr) ? "true" : "false");
140  APPEND(tmpBuf);
141  break;
142  }
143  case 'B': {
144  *bufp++ = '[';
145  if (bufp == &printString[PRINT_BUF_SIZE])
146  break;
147  for (int i = 0; i < width; ++i) {
148  if (mask & (1ull << i)) {
149  sprintf(tmpBuf, "%s", ((Bool *)ptr)[i] ? "true" : "false");
150  APPEND(tmpBuf);
151  }
152  else
153  APPEND("_________");
154  *bufp++ = (i != width-1) ? ',' : ']';
155  }
156  break;
157  }
158  case 'i': PRINT_SCALAR("%d", int);
159  case 'I': PRINT_VECTOR("%d", int);
160  case 'u': PRINT_SCALAR("%u", unsigned int);
161  case 'U': PRINT_VECTOR("%u", unsigned int);
162  case 'f': PRINT_SCALAR("%f", float);
163  case 'F': PRINT_VECTOR("%f", float);
164  case 'l': PRINT_SCALAR("%lld", long long);
165  case 'L': PRINT_VECTOR("%lld", long long);
166  case 'v': PRINT_SCALAR("%llu", unsigned long long);
167  case 'V': PRINT_VECTOR("%llu", unsigned long long);
168  case 'd': PRINT_SCALAR("%f", double);
169  case 'D': PRINT_VECTOR("%f", double);
170  case 'p': PRINT_SCALAR("%p", void *);
171  case 'P': PRINT_VECTOR("%p", void *);
172  default:
173  APPEND("UNKNOWN TYPE ");
174  *bufp++ = *types;
175  }
176  ++types;
177  }
178  }
179  ++format;
180  }
181 
182  done:
183  *bufp = '\0';
184  fputs(printString, stdout);
185  fflush(stdout);
186 }
187 
188 /* this is print for PTX target only */
189 int __puts_nvptx(const char *);
190 void __do_print_nvptx(const char *format, const char *types, int width, uint64_t mask,
191  void **args) {
192 #if 0
193  char printString[PRINT_BUF_SIZE+1]; // +1 for trailing NUL
194  char *bufp = &printString[0];
195  char tmpBuf[256];
196 
197  int argCount = 0;
198  while (*format && bufp < &printString[PRINT_BUF_SIZE]) {
199  // Format strings are just single percent signs.
200  if (*format != '%') {
201  *bufp++ = *format;
202  }
203  else {
204  if (*types) {
205  void *ptr = args[argCount++];
206  // Based on the encoding in the types string, cast the
207  // value appropriately and print it with a reasonable
208  // printf() formatting string.
209  switch (*types) {
210  case 'b': {
211  sprintf(tmpBuf, "%s", *((Bool *)ptr) ? "true" : "false");
212  APPEND(tmpBuf);
213  break;
214  }
215  case 'B': {
216  *bufp++ = '[';
217  if (bufp == &printString[PRINT_BUF_SIZE])
218  break;
219  for (int i = 0; i < width; ++i) {
220  if (mask & (1ull << i)) {
221  sprintf(tmpBuf, "%s", ((Bool *)ptr)[i] ? "true" : "false");
222  APPEND(tmpBuf);
223  }
224  else
225  APPEND("_________");
226  *bufp++ = (i != width-1) ? ',' : ']';
227  }
228  break;
229  }
230  case 'i': PRINT_SCALAR("%d", int);
231  case 'I': PRINT_VECTOR("%d", int);
232  case 'u': PRINT_SCALAR("%u", unsigned int);
233  case 'U': PRINT_VECTOR("%u", unsigned int);
234  case 'f': PRINT_SCALAR("%f", float);
235  case 'F': PRINT_VECTOR("%f", float);
236  case 'l': PRINT_SCALAR("%lld", long long);
237  case 'L': PRINT_VECTOR("%lld", long long);
238  case 'v': PRINT_SCALAR("%llu", unsigned long long);
239  case 'V': PRINT_VECTOR("%llu", unsigned long long);
240  case 'd': PRINT_SCALAR("%f", double);
241  case 'D': PRINT_VECTOR("%f", double);
242  case 'p': PRINT_SCALAR("%p", void *);
243  case 'P': PRINT_VECTOR("%p", void *);
244  default:
245  APPEND("UNKNOWN TYPE ");
246  *bufp++ = *types;
247  }
248  ++types;
249  }
250  }
251  ++format;
252  }
253 
254  done:
255  *bufp = '\n'; bufp++;
256  *bufp = '\0';
257  __puts_nvptx(printString);
258 #else
259  __puts_nvptx("---nvptx printing is not support---\n");
260 #endif
261 }
262 
263 
264 int __num_cores() {
265 #if defined(_MSC_VER) || defined(__MINGW32__)
266  // This is quite a hack. Including all of windows.h to get this definition
267  // pulls in a bunch of stuff that leads to undefined symbols at link time.
268  // So we don't #include <windows.h> but instead have the equivalent declarations
269  // here. Presumably this struct declaration won't be changing in the future
270  // anyway...
271  struct SYSTEM_INFO {
272  int pad0[2];
273  void *pad1[2];
274  int *pad2;
275  int dwNumberOfProcessors;
276  int pad3[3];
277  };
278 
279  struct SYSTEM_INFO sysInfo;
280  extern void __stdcall GetSystemInfo(struct SYSTEM_INFO *);
281  GetSystemInfo(&sysInfo);
282  return sysInfo.dwNumberOfProcessors;
283 #else
284  return sysconf(_SC_NPROCESSORS_ONLN);
285 #endif // !_MSC_VER
286 }
int __puts_nvptx(const char *)
int __num_cores()
Definition: builtins.c:264
void __do_print_nvptx(const char *format, const char *types, int width, uint64_t mask, void **args)
Definition: builtins.c:190
#define PRINT_SCALAR(fmt, type)
Definition: builtins.c:89
#define PRINT_BUF_SIZE
Definition: builtins.c:76
int Bool
Definition: builtins.c:74
void __do_print(const char *format, const char *types, int width, uint64_t mask, void **args)
Definition: builtins.c:119
#define APPEND(str)
Definition: builtins.c:78
#define PRINT_VECTOR(fmt, type)
Definition: builtins.c:94