Intel SPMD Program Compiler  1.11.0
module.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 module.cpp
35  @brief Impementation of the Module class, which collects the result of compiling
36  a source file and then generates output (object files, etc.)
37 */
38 
39 #include "module.h"
40 #include "builtins.h"
41 #include "ctx.h"
42 #include "expr.h"
43 #include "func.h"
44 #include "llvmutil.h"
45 #include "opt.h"
46 #include "stmt.h"
47 #include "sym.h"
48 #include "type.h"
49 #include "util.h"
50 
51 #include <algorithm>
52 #include <ctype.h>
53 #include <fcntl.h>
54 #include <iostream>
55 #include <set>
56 #include <sstream>
57 #include <stdarg.h>
58 #include <stdio.h>
59 #include <sys/stat.h>
60 #include <sys/types.h>
61 #ifdef ISPC_NVPTX_ENABLED
62 #include <map>
63 #endif /* ISPC_NVPTX_ENABLED */
64 #ifdef ISPC_IS_WINDOWS
65 #include <io.h>
66 #include <windows.h>
67 #define strcasecmp stricmp
68 #endif
69 #if ISPC_LLVM_VERSION == ISPC_LLVM_3_2
70 #include <llvm/DerivedTypes.h>
71 #include <llvm/Instructions.h>
72 #include <llvm/Intrinsics.h>
73 #include <llvm/LLVMContext.h>
74 #include <llvm/Module.h>
75 #include <llvm/Type.h>
76 #ifdef ISPC_NVPTX_ENABLED
77 #include "llvm/Assembly/AssemblyAnnotationWriter.h"
78 #endif /* ISPC_NVPTX_ENABLED */
79 #else
80 #include <llvm/IR/DerivedTypes.h>
81 #include <llvm/IR/Instructions.h>
82 #include <llvm/IR/Intrinsics.h>
83 #include <llvm/IR/LLVMContext.h>
84 #include <llvm/IR/Module.h>
85 #include <llvm/IR/Type.h>
86 #ifdef ISPC_NVPTX_ENABLED
87 #if ISPC_LLVM_VERSION >= ISPC_LLVM_3_5 /* 3.5+ */
88 #include <llvm/IR/AssemblyAnnotationWriter.h>
89 #else
90 #include <llvm/Assembly/AssemblyAnnotationWriter.h>
91 #endif
92 #endif /* ISPC_NVPTX_ENABLED */
93 #endif
94 #if ISPC_LLVM_VERSION <= ISPC_LLVM_3_6
95 #include "llvm/PassManager.h"
96 #else // LLVM 3.7+
97 #include "llvm/IR/LegacyPassManager.h"
98 #endif
99 #include <llvm/PassRegistry.h>
100 #include <llvm/Support/FileUtilities.h>
101 #include <llvm/Support/FormattedStream.h>
102 #include <llvm/Target/TargetMachine.h>
103 #include <llvm/Target/TargetOptions.h>
104 #include <llvm/Transforms/IPO.h>
105 #if ISPC_LLVM_VERSION == ISPC_LLVM_3_2
106 #include <llvm/DataLayout.h>
107 #include <llvm/TargetTransformInfo.h>
108 #else // LLVM 3.3+
109 #include <llvm/Analysis/TargetTransformInfo.h>
110 #include <llvm/IR/DataLayout.h>
111 #endif
112 #if ISPC_LLVM_VERSION >= ISPC_LLVM_3_5
113 #include <llvm/IR/CFG.h>
114 #include <llvm/IR/IRPrintingPasses.h>
115 #include <llvm/IR/InstIterator.h>
116 #include <llvm/IR/Verifier.h>
117 #else
118 #include <llvm/Analysis/Verifier.h>
119 #include <llvm/Assembly/PrintModulePass.h>
120 #include <llvm/Support/CFG.h>
121 #include <llvm/Support/InstIterator.h>
122 #endif
123 #include <clang/Basic/TargetInfo.h>
124 #include <clang/Frontend/CompilerInstance.h>
125 #include <clang/Frontend/TextDiagnosticPrinter.h>
126 #include <clang/Frontend/Utils.h>
127 #include <clang/Lex/PreprocessorOptions.h>
128 #include <llvm/Support/Host.h>
129 #include <llvm/Support/ToolOutputFile.h>
130 #include <llvm/Support/raw_ostream.h>
131 #if ISPC_LLVM_VERSION <= ISPC_LLVM_3_9
132 #include <llvm/Bitcode/ReaderWriter.h>
133 #else
134 #include <llvm/Bitcode/BitcodeWriter.h>
135 #endif
136 
137 /*! list of files encountered by the parser. this allows emitting of
138  the module file's dependencies via the -MMM option */
139 std::set<std::string> registeredDependencies;
140 
141 /*! this is where the parser tells us that it has seen the given file
142  name in the CPP hash */
143 void RegisterDependency(const std::string &fileName) {
144  if (fileName[0] != '<' && fileName != "stdlib.ispc")
145  registeredDependencies.insert(fileName);
146 }
147 
148 static void lDeclareSizeAndPtrIntTypes(SymbolTable *symbolTable) {
150  ptrIntType = ptrIntType->GetAsUnboundVariabilityType();
151 
152  symbolTable->AddType("intptr_t", ptrIntType, SourcePos());
153  symbolTable->AddType("uintptr_t", ptrIntType->GetAsUnsignedType(), SourcePos());
154  symbolTable->AddType("ptrdiff_t", ptrIntType, SourcePos());
155 
156  const Type *sizeType =
158  sizeType = sizeType->GetAsUnboundVariabilityType();
159  symbolTable->AddType("size_t", sizeType, SourcePos());
160 }
161 
162 /** After compilation completes, there's often a lot of extra debugging
163  metadata left around that isn't needed any more--for example, for
164  static functions that weren't actually used, function information for
165  functions that were inlined, etc. This function takes a llvm::Module
166  and tries to strip out all of this extra stuff.
167  */
168 static void lStripUnusedDebugInfo(llvm::Module *module) {
169 #if ISPC_LLVM_VERSION >= ISPC_LLVM_3_9
170  // In LLVM 3.9 Global DCE is much more efficient than the LLVM 3.8's one.
171  // So, the fruitfulness of this function is negligible.
172  return;
173 #else
174  if (g->generateDebuggingSymbols == false)
175  return;
176 #if ISPC_LLVM_VERSION <= ISPC_LLVM_3_5 // <= 3.5
177  std::set<llvm::Value *> SPall;
178 #else // LLVM 3.6+
179  std::set<llvm::Metadata *> SPall;
180 #endif
181  // OK, now we are to determine which functions actually survived the
182  // optimization. We will now read all IR instructions in the module.
183  //
184  // for every function in the module
185  for (llvm::Module::const_iterator f = module->begin(), fe = module->end(); f != fe; ++f) {
186  /// for every instruction in the function
187  for (llvm::const_inst_iterator i = llvm::inst_begin(&(*f)), ie = llvm::inst_end(&(*f)); i != ie; ++i) {
188  const llvm::Instruction *inst = &(*i);
189  // get the instruction`s debugging metadata
190  llvm::MDNode *node = inst->getMetadata(llvm::LLVMContext::MD_dbg);
191  while (node) {
192  // get the scope of the current instruction`s location
193  // node becomes NULL if this was the original location
194 #if ISPC_LLVM_VERSION <= ISPC_LLVM_3_6 // <= 3.6
195  llvm::DILocation dloc(node);
196  llvm::DIScope scope = dloc.getScope();
197  node = dloc.getOrigLocation();
198  // now following a chain of nested scopes
199  while (!0) {
200  if (scope.isLexicalBlockFile())
201  scope = llvm::DILexicalBlockFile(scope).getScope();
202  else if (scope.isLexicalBlock())
203  scope = llvm::DILexicalBlock(scope).getContext();
204  else if (scope.isNameSpace())
205  scope = llvm::DINameSpace(scope).getContext();
206  else
207  break;
208  }
209  if (scope.isSubprogram()) {
210 #else // LLVM 3.7+
211  llvm::DILocation *dloc = llvm::cast<llvm::DILocation>(node);
212  llvm::DIScope *scope = dloc->getScope();
213  // llvm::MDLocation *dloc = llvm::cast<llvm::MDLocation>(node);
214  // llvm::MDScope *scope = dloc->getScope();
215  node = dloc->getInlinedAt();
216  // now following a chain of nested scopes
217  while (!0) {
218  if (llvm::isa<llvm::DILexicalBlockFile>(scope))
219  scope = llvm::cast<llvm::DILexicalBlockFile>(scope)->getScope();
220  else if (llvm::isa<llvm::DILexicalBlockBase>(scope))
221  scope = llvm::cast<llvm::DILexicalBlockBase>(scope)->getScope();
222  else if (llvm::isa<llvm::DINamespace>(scope))
223  scope = llvm::cast<llvm::DINamespace>(scope)->getScope();
224  else
225  break;
226  }
227  if (llvm::isa<llvm::DISubprogram>(scope)) {
228 #endif
229  // good, the chain ended with a function; adding
230  SPall.insert(scope);
231  }
232  }
233  }
234  }
235  // loop over the compile units that contributed to the final module
236  if (llvm::NamedMDNode *cuNodes = module->getNamedMetadata("llvm.dbg.cu")) {
237  for (unsigned i = 0, ie = cuNodes->getNumOperands(); i != ie; ++i) {
238  llvm::MDNode *cuNode = cuNodes->getOperand(i);
239 #if ISPC_LLVM_VERSION <= ISPC_LLVM_3_6
240  llvm::DICompileUnit cu(cuNode);
241  llvm::DIArray subprograms = cu.getSubprograms();
242  if (subprograms.getNumElements() == 0) {
243 #else /* LLVM 3.7+ */
244  llvm::DICompileUnit *cu = llvm::cast<llvm::DICompileUnit>(cuNode);
245  llvm::DISubprogramArray subprograms = cu->getSubprograms();
246  // llvm::MDCompileUnit *cu = llvm::cast<llvm::MDCompileUnit>(cuNode);
247  // llvm::MDSubprogramArray subprograms = cu->getSubprograms();
248  if (subprograms.size() == 0) {
249 #endif
250  continue;
251  }
252 #if ISPC_LLVM_VERSION <= ISPC_LLVM_3_5
253  std::set<llvm::Value *> SPset;
254  std::vector<llvm::Value *> usedSubprograms;
255 #else /* LLVM 3.6+ */
256  std::set<llvm::Metadata *> SPset;
257  std::vector<llvm::Metadata *> usedSubprograms;
258 #endif
259 
260  // determine what functions of those extracted belong to the unit
261 #if ISPC_LLVM_VERSION <= ISPC_LLVM_3_6
262  for (unsigned j = 0, je = subprograms.getNumElements(); j != je; ++j)
263 #else /* LLVM 3.7+ */
264  for (unsigned j = 0, je = subprograms.size(); j != je; ++j)
265 #endif
266 #if ISPC_LLVM_VERSION <= ISPC_LLVM_3_5
267  SPset.insert(subprograms->getOperand(j));
268 #elif ISPC_LLVM_VERSION == ISPC_LLVM_3_6
269  SPset.insert(subprograms.getElement(j));
270 #else // LLVM 3.7+
271  SPset.insert(subprograms[j]);
272 #endif
273 
274  std::set_intersection(SPall.begin(), SPall.end(), SPset.begin(), SPset.end(),
275  std::back_inserter(usedSubprograms));
276 
277  Debug(SourcePos(),
278  "%d / %d functions left in module with debug "
279  "info.",
280  (int)usedSubprograms.size(),
281 #if ISPC_LLVM_VERSION <= ISPC_LLVM_3_6
282  (int)subprograms.getNumElements());
283 #else /* LLVM 3.7+ */
284  (int)subprograms.size());
285 #endif
286 
287  // We'd now like to replace the array of subprograms in the
288  // compile unit with only the ones that actually have function
289  // definitions present. Unfortunately, llvm::DICompileUnit
290  // doesn't provide a method to set the subprograms. Therefore,
291  // we end up needing to directly stuff a new array into the
292  // appropriate slot (number 12) in the MDNode for the compile
293  // unit.
294  //
295  // Because this is all so hard-coded and would break if the
296  // debugging metadata organization on the LLVM side changed,
297  // here is a bunch of asserting to make sure that element 12 of
298  // the compile unit's MDNode has the subprograms array....
299  //
300  // Update: This is not an approved way of working with debug info
301  // metadata. It's not supposed to be deleted. But in out use-case
302  // it's quite useful thing, as we link in bunch of unnecessary
303  // stuff and remove it later on. Removing it is useful, as it
304  // reduces size of the binary significantly (manyfold for small
305  // programs).
306 #if ISPC_LLVM_VERSION == ISPC_LLVM_3_2 // 3.2
307  llvm::MDNode *nodeSPMD = llvm::dyn_cast<llvm::MDNode>(cuNode->getOperand(12));
308  Assert(nodeSPMD != NULL);
309  llvm::MDNode *nodeSPMDArray = llvm::dyn_cast<llvm::MDNode>(nodeSPMD->getOperand(0));
310  llvm::DIArray nodeSPs(nodeSPMDArray);
311  Assert(nodeSPs.getNumElements() == subprograms.getNumElements());
312  for (int i = 0; i < (int)nodeSPs.getNumElements(); ++i)
313  Assert(nodeSPs.getElement(i) == subprograms.getElement(i));
314 
315  // And now we can go and stuff it into the node with some
316  // confidence...
317  llvm::Value *usedSubprogramsArray =
318  m->diBuilder->getOrCreateArray(llvm::ArrayRef<llvm::Value *>(usedSubprograms));
319  llvm::MDNode *replNode = llvm::MDNode::get(*g->ctx, llvm::ArrayRef<llvm::Value *>(usedSubprogramsArray));
320  cuNode->replaceOperandWith(12, replNode);
321 #elif ISPC_LLVM_VERSION <= ISPC_LLVM_3_5 // 3.3, 3.4, 3.5
322  llvm::MDNode *nodeSPMDArray = llvm::dyn_cast<llvm::MDNode>(cuNode->getOperand(9));
323  Assert(nodeSPMDArray != NULL);
324  llvm::DIArray nodeSPs(nodeSPMDArray);
325  Assert(nodeSPs.getNumElements() == subprograms.getNumElements());
326  for (int i = 0; i < (int)nodeSPs.getNumElements(); ++i)
327  Assert(nodeSPs.getElement(i) == subprograms.getElement(i));
328 
329  // And now we can go and stuff it into the node with some
330  // confidence...
331  llvm::MDNode *replNode = m->diBuilder->getOrCreateArray(llvm::ArrayRef<llvm::Value *>(usedSubprograms));
332  cuNode->replaceOperandWith(9, replNode);
333 #elif ISPC_LLVM_VERSION == ISPC_LLVM_3_6 // 3.6
334  llvm::DIArray nodeSPs = cu.getSubprograms();
335  Assert(nodeSPs.getNumElements() == subprograms.getNumElements());
336  for (int i = 0; i < (int)nodeSPs.getNumElements(); ++i)
337  Assert(nodeSPs.getElement(i) == subprograms.getElement(i));
338 
339  // And now we can go and stuff it into the unit with some
340  // confidence...
341  llvm::MDNode *replNode = llvm::MDNode::get(module->getContext(),
342  llvm::ArrayRef<llvm::Metadata *>(usedSubprograms));
343  cu.replaceSubprograms(llvm::DIArray(replNode));
344 #else // LLVM 3.7+
345  llvm::DISubprogramArray nodeSPs = cu->getSubprograms();
346  //llvm::MDSubprogramArray nodeSPs = cu->getSubprograms();
347  Assert(nodeSPs.size() == subprograms.size());
348  for (int i = 0; i < (int)nodeSPs.size(); ++i)
349  Assert(nodeSPs [i] == subprograms [i]);
350 
351  // And now we can go and stuff it into the unit with some
352  // confidence...
353  cu->replaceSubprograms(llvm::MDTuple::get(cu->getContext(),
354  llvm::ArrayRef<llvm::Metadata *>(usedSubprograms)));
355 #endif
356  }
357  }
358 
359  // Also, erase a bunch of named metadata detrius; for each function
360  // there is sometimes named metadata llvm.dbg.lv.{funcname} that
361  // doesn't seem to be otherwise needed.
362  std::vector<llvm::NamedMDNode *> toErase;
363  llvm::Module::named_metadata_iterator iter = module->named_metadata_begin();
364  for (; iter != module->named_metadata_end(); ++iter) {
365  if (!strncmp(iter->getName().str().c_str(), "llvm.dbg.lv", 11))
366  toErase.push_back(&*iter);
367  }
368  for (int i = 0; i < (int)toErase.size(); ++i)
369  module->eraseNamedMetadata(toErase[i]);
370 #endif
371 }
372 
373 ///////////////////////////////////////////////////////////////////////////
374 // Module
375 
376 Module::Module(const char *fn) {
377  // It's a hack to do this here, but it must be done after the target
378  // information has been set (so e.g. the vector width is known...) In
379  // particular, if we're compiling to multiple targets with different
380  // vector widths, this needs to be redone each time through.
381  InitLLVMUtil(g->ctx, *g->target);
382 
383  filename = fn;
384  errorCount = 0;
385  symbolTable = new SymbolTable;
386  ast = new AST;
387 
389 
390  module = new llvm::Module(filename ? filename : "<stdin>", *g->ctx);
391  module->setTargetTriple(g->target->GetTripleString());
392 
393  // DataLayout information supposed to be managed in single place in Target class.
394  module->setDataLayout(g->target->getDataLayout()->getStringRepresentation());
395 
397 #if ISPC_LLVM_VERSION >= ISPC_LLVM_3_8
398  // TODO: what to do in case of cross-compilation?
399  // i.e. in case of PS4.
400 #ifdef ISPC_IS_WINDOWS
401  // To enable debug information on Windows, we have to let llvm know, that
402  // debug information should be emitted in CodeView format.
403  module->addModuleFlag(llvm::Module::Warning, "CodeView", 1);
404 #else
405  module->addModuleFlag(llvm::Module::Warning, "Dwarf Version", g->generateDWARFVersion);
406 #endif
407 #endif
408  diBuilder = new llvm::DIBuilder(*module);
409 
410  // Let the DIBuilder know that we're starting a new compilation
411  // unit.
412  if (filename == NULL) {
413  // Unfortunately we can't yet call Error() since the global 'm'
414  // variable hasn't been initialized yet.
415  fprintf(stderr, "Can't emit debugging information with no "
416  "source file on disk.\n");
417  ++errorCount;
418  delete diBuilder;
419  diBuilder = NULL;
420  } else {
421  std::string directory, name;
422  GetDirectoryAndFileName(g->currentDirectory, filename, &directory, &name);
423  char producerString[512];
424 #if defined(BUILD_VERSION) && defined(BUILD_DATE)
425  snprintf(producerString, sizeof(producerString), "ispc version %s (build %s on %s)", ISPC_VERSION,
426  BUILD_VERSION, BUILD_DATE);
427 #else
428  snprintf(producerString, sizeof(producerString), "ispc version %s (built on %s)", ISPC_VERSION, __DATE__);
429 #endif
430 #if ISPC_LLVM_VERSION <= ISPC_LLVM_3_3
431  diBuilder->createCompileUnit(llvm::dwarf::DW_LANG_C99, /* lang */
432  name, /* filename */
433  directory, /* directory */
434  producerString, /* producer */
435  g->opt.level > 0 /* is optimized */, "-g", /* command line args */
436  0 /* run time version */);
437 #elif ISPC_LLVM_VERSION <= ISPC_LLVM_3_9 // LLVM 3.4-3.9
438  diCompileUnit =
439  diBuilder->createCompileUnit(llvm::dwarf::DW_LANG_C99, /* lang */
440  name, /* filename */
441  directory, /* directory */
442  producerString, /* producer */
443  g->opt.level > 0 /* is optimized */, "-g", /* command line args */
444  0 /* run time version */);
445 #elif ISPC_LLVM_VERSION >= ISPC_LLVM_4_0 // LLVM 4.0+
446  auto srcFile = diBuilder->createFile(name, directory);
447  diCompileUnit =
448  diBuilder->createCompileUnit(llvm::dwarf::DW_LANG_C99, /* lang */
449  srcFile, /* filename */
450  producerString, /* producer */
451  g->opt.level > 0 /* is optimized */, "-g", /* command line args */
452  0 /* run time version */);
453 #endif
454  }
455  } else
456  diBuilder = NULL;
457 }
458 
459 extern FILE *yyin;
460 extern int yyparse();
461 typedef struct yy_buffer_state *YY_BUFFER_STATE;
463 extern YY_BUFFER_STATE yy_scan_string(const char *);
464 extern YY_BUFFER_STATE yy_create_buffer(FILE *, int);
465 extern void yy_delete_buffer(YY_BUFFER_STATE);
466 
468  extern void ParserInit();
469  ParserInit();
470 
471  // FIXME: it'd be nice to do this in the Module constructor, but this
472  // function ends up calling into routines that expect the global
473  // variable 'm' to be initialized and available (which it isn't until
474  // the Module constructor returns...)
476 
477  bool runPreprocessor = g->runCPP;
478 
479  if (runPreprocessor) {
480  if (filename != NULL) {
481  // Try to open the file first, since otherwise we crash in the
482  // preprocessor if the file doesn't exist.
483  FILE *f = fopen(filename, "r");
484  if (!f) {
485  perror(filename);
486  return 1;
487  }
488  fclose(f);
489  }
490 
491  std::string buffer;
492  llvm::raw_string_ostream os(buffer);
493  execPreprocessor((filename != NULL) ? filename : "-", &os);
494  YY_BUFFER_STATE strbuf = yy_scan_string(os.str().c_str());
495  yyparse();
496  yy_delete_buffer(strbuf);
497  } else {
498  // No preprocessor, just open up the file if it's not stdin..
499  FILE *f = NULL;
500  if (filename == NULL)
501  f = stdin;
502  else {
503  f = fopen(filename, "r");
504  if (f == NULL) {
505  perror(filename);
506  return 1;
507  }
508  }
509  yyin = f;
511  yyparse();
512  fclose(f);
513  }
514 
515 #if ISPC_LLVM_VERSION >= ISPC_LLVM_3_7 // LLVM 3.7+
516  if (g->NoOmitFramePointer)
517  for (llvm::Function &f : *module)
518  f.addFnAttr("no-frame-pointer-elim", "true");
519 #endif
520  for (llvm::Function &f : *module)
522  ast->GenerateIR();
523 
524  if (diBuilder)
525  diBuilder->finalize();
526  if (errorCount == 0)
528 
529  return errorCount;
530 }
531 
532 void Module::AddTypeDef(const std::string &name, const Type *type, SourcePos pos) {
533  // Typedefs are easy; just add the mapping between the given name and
534  // the given type.
535  symbolTable->AddType(name.c_str(), type, pos);
536 }
537 
538 void Module::AddGlobalVariable(const std::string &name, const Type *type, Expr *initExpr, bool isConst,
539  StorageClass storageClass, SourcePos pos) {
540  // These may be NULL due to errors in parsing; just gracefully return
541  // here if so.
542  if (name == "" || type == NULL) {
543  Assert(errorCount > 0);
544  return;
545  }
546 
547  if (symbolTable->LookupFunction(name.c_str())) {
548  Error(pos,
549  "Global variable \"%s\" shadows previously-declared "
550  "function.",
551  name.c_str());
552  return;
553  }
554 
555  if (storageClass == SC_EXTERN_C) {
556  Error(pos, "extern \"C\" qualifier can only be used for "
557  "functions.");
558  return;
559  }
560 
561  if (type->IsVoidType()) {
562  Error(pos, "\"void\" type global variable is illegal.");
563  return;
564  }
565 
566  type = ArrayType::SizeUnsizedArrays(type, initExpr);
567  if (type == NULL)
568  return;
569 
570  const ArrayType *at = CastType<ArrayType>(type);
571  if (at != NULL && at->TotalElementCount() == 0) {
572  Error(pos, "Illegal to declare a global variable with unsized "
573  "array dimensions that aren't set with an initializer "
574  "expression.");
575  return;
576  }
577 
578 #ifdef ISPC_NVPTX_ENABLED
579  if (g->target->getISA() == Target::NVPTX &&
580 #if 0
581  !type->IsConstType() &&
582 #endif
583 #if 1
584  at != NULL &&
585 #endif
586  type->IsVaryingType()) {
587  Error(pos, "Global \"varying\" variables are not yet supported in \"nvptx\" target.");
588  return;
589 #if 0
590  int nel = 32; /* warp-size */
591  if (type->IsArrayType())
592  {
593  const ArrayType *at = CastType<ArrayType>(type);
594  /* we must scale # elements by 4, because a thread-block will run 4 warps
595  * or 128 threads.
596  * ***note-to-me***:please define these value (128threads/4warps)
597  * in nvptx-target definition
598  * instead of compile-time constants
599  */
600  nel *= at->GetElementCount();
601  assert (!type->IsSOAType());
602  type = new ArrayType(at->GetElementType()->GetAsUniformType(), nel);
603  }
604  else
605  type = new ArrayType(type->GetAsUniformType(), nel);
606 #endif
607  }
608 #endif /* ISPC_NVPTX_ENABLED */
609 
610  llvm::Type *llvmType = type->LLVMType(g->ctx);
611  if (llvmType == NULL)
612  return;
613 
614  // See if we have an initializer expression for the global. If so,
615  // make sure it's a compile-time constant!
616  llvm::Constant *llvmInitializer = NULL;
617  ConstExpr *constValue = NULL;
618  if (storageClass == SC_EXTERN || storageClass == SC_EXTERN_C) {
619  if (initExpr != NULL)
620  Error(pos,
621  "Initializer can't be provided with \"extern\" "
622  "global variable \"%s\".",
623  name.c_str());
624  } else {
625  if (initExpr != NULL) {
626  initExpr = TypeCheck(initExpr);
627  if (initExpr != NULL) {
628  // We need to make sure the initializer expression is
629  // the same type as the global. (But not if it's an
630  // ExprList; they don't have types per se / can't type
631  // convert themselves anyway.)
632  if (llvm::dyn_cast<ExprList>(initExpr) == NULL)
633  initExpr = TypeConvertExpr(initExpr, type, "initializer");
634 
635  if (initExpr != NULL) {
636  initExpr = Optimize(initExpr);
637  // Fingers crossed, now let's see if we've got a
638  // constant value..
639  llvmInitializer = initExpr->GetConstant(type);
640 
641  if (llvmInitializer != NULL) {
642  if (type->IsConstType())
643  // Try to get a ConstExpr associated with
644  // the symbol. This llvm::dyn_cast can
645  // validly fail, for example for types like
646  // StructTypes where a ConstExpr can't
647  // represent their values.
648  constValue = llvm::dyn_cast<ConstExpr>(initExpr);
649  } else
650  Error(initExpr->pos,
651  "Initializer for global variable \"%s\" "
652  "must be a constant.",
653  name.c_str());
654  }
655  }
656  }
657 
658  // If no initializer was provided or if we couldn't get a value
659  // above, initialize it with zeros..
660  if (llvmInitializer == NULL)
661  llvmInitializer = llvm::Constant::getNullValue(llvmType);
662  }
663 
664  Symbol *sym = symbolTable->LookupVariable(name.c_str());
665  llvm::GlobalVariable *oldGV = NULL;
666  if (sym != NULL) {
667  // We've already seen either a declaration or a definition of this
668  // global.
669 
670  // If the type doesn't match with the previous one, issue an error.
671  if (!Type::Equal(sym->type, type) ||
672  (sym->storageClass != SC_EXTERN && sym->storageClass != SC_EXTERN_C && sym->storageClass != storageClass)) {
673  Error(pos,
674  "Definition of variable \"%s\" conflicts with "
675  "definition at %s:%d.",
676  name.c_str(), sym->pos.name, sym->pos.first_line);
677  return;
678  }
679 
680  llvm::GlobalVariable *gv = llvm::dyn_cast<llvm::GlobalVariable>(sym->storagePtr);
681  Assert(gv != NULL);
682 
683  // And issue an error if this is a redefinition of a variable
684  if (gv->hasInitializer() && sym->storageClass != SC_EXTERN && sym->storageClass != SC_EXTERN_C) {
685  Error(pos,
686  "Redefinition of variable \"%s\" is illegal. "
687  "(Previous definition at %s:%d.)",
688  sym->name.c_str(), sym->pos.name, sym->pos.first_line);
689  return;
690  }
691 
692  // Now, we either have a redeclaration of a global, or a definition
693  // of a previously-declared global. First, save the pointer to the
694  // previous llvm::GlobalVariable
695  oldGV = gv;
696  } else {
697  sym = new Symbol(name, pos, type, storageClass);
698  symbolTable->AddVariable(sym);
699  }
700  sym->constValue = constValue;
701 
702  llvm::GlobalValue::LinkageTypes linkage =
703  (sym->storageClass == SC_STATIC) ? llvm::GlobalValue::InternalLinkage : llvm::GlobalValue::ExternalLinkage;
704 
705  // Note that the NULL llvmInitializer is what leads to "extern"
706  // declarations coming up extern and not defining storage (a bit
707  // subtle)...
708  sym->storagePtr = new llvm::GlobalVariable(*module, llvmType, isConst, linkage, llvmInitializer, sym->name.c_str());
709 
710  // Patch up any references to the previous GlobalVariable (e.g. from a
711  // declaration of a global that was later defined.)
712  if (oldGV != NULL) {
713  oldGV->replaceAllUsesWith(sym->storagePtr);
714  oldGV->removeFromParent();
715  sym->storagePtr->setName(sym->name.c_str());
716  }
717 
718  if (diBuilder) {
719 #if ISPC_LLVM_VERSION <= ISPC_LLVM_3_5 // 3.2, 3.3, 3.4, 3.5
720  llvm::DIFile file = pos.GetDIFile();
721  llvm::DIGlobalVariable var = diBuilder->createGlobalVariable(
722  name, file, pos.first_line, sym->type->GetDIType(file), (sym->storageClass == SC_STATIC), sym->storagePtr);
723 #elif ISPC_LLVM_VERSION == ISPC_LLVM_3_6 // 3.6
724  llvm::DIFile file = pos.GetDIFile();
725  llvm::Constant *sym_const_storagePtr = llvm::dyn_cast<llvm::Constant>(sym->storagePtr);
726  Assert(sym_const_storagePtr);
727  llvm::DIGlobalVariable var =
728  diBuilder->createGlobalVariable(file, name, name, file, pos.first_line, sym->type->GetDIType(file),
729  (sym->storageClass == SC_STATIC), sym_const_storagePtr);
730 #elif ISPC_LLVM_VERSION >= ISPC_LLVM_3_7 && ISPC_LLVM_VERSION <= ISPC_LLVM_3_9 // LLVM 3.7 - 3.9
731  llvm::DIFile *file = pos.GetDIFile();
732  // llvm::MDFile *file = pos.GetDIFile();
733  llvm::Constant *sym_const_storagePtr = llvm::dyn_cast<llvm::Constant>(sym->storagePtr);
734  Assert(sym_const_storagePtr);
735  diBuilder->createGlobalVariable(file, name, name, file, pos.first_line, sym->type->GetDIType(file),
736  (sym->storageClass == SC_STATIC), sym_const_storagePtr);
737 #else // LLVM 4.0+
738  llvm::DIFile *file = pos.GetDIFile();
739  // llvm::MDFile *file = pos.GetDIFile();
740  llvm::GlobalVariable *sym_GV_storagePtr = llvm::dyn_cast<llvm::GlobalVariable>(sym->storagePtr);
741  Assert(sym_GV_storagePtr);
742  llvm::DIGlobalVariableExpression *var = diBuilder->createGlobalVariableExpression(
743  file, name, name, file, pos.first_line, sym->type->GetDIType(file), (sym->storageClass == SC_STATIC));
744  sym_GV_storagePtr->addDebugInfo(var);
745 #endif
746 #if ISPC_LLVM_VERSION <= ISPC_LLVM_3_6
747  Assert(var.Verify());
748 #else // LLVM 3.7+
749  // comming soon
750 #endif
751  }
752 }
753 
754 /** Given an arbitrary type, see if it or any of the leaf types contained
755  in it has a type that's illegal to have exported to C/C++
756  code.
757 
758  (Note that it's fine for the original struct or a contained struct to
759  be varying, so long as all of its members have bound 'uniform'
760  variability.)
761 
762  This functions returns true and issues an error if are any illegal
763  types are found and returns false otherwise.
764 */
765 static bool lRecursiveCheckValidParamType(const Type *t, bool vectorOk) {
766  const StructType *st = CastType<StructType>(t);
767  if (st != NULL) {
768  for (int i = 0; i < st->GetElementCount(); ++i)
769  if (!lRecursiveCheckValidParamType(st->GetElementType(i), vectorOk))
770  return false;
771  return true;
772  }
773 
774  // Vector types are also not supported, pending ispc properly
775  // supporting the platform ABI. (Pointers to vector types are ok,
776  // though.) (https://github.com/ispc/ispc/issues/363)...
777  if (vectorOk == false && CastType<VectorType>(t) != NULL)
778  return false;
779 
780  const SequentialType *seqt = CastType<SequentialType>(t);
781  if (seqt != NULL)
782  return lRecursiveCheckValidParamType(seqt->GetElementType(), vectorOk);
783 
784  const PointerType *pt = CastType<PointerType>(t);
785  if (pt != NULL) {
786  // Only allow exported uniform pointers
787  // Uniform pointers to varying data, however, are ok.
788  if (pt->IsVaryingType())
789  return false;
790  else
791  return lRecursiveCheckValidParamType(pt->GetBaseType(), true);
792  }
793 
794  if (t->IsVaryingType() && !vectorOk)
795  return false;
796  else
797  return true;
798 }
799 
800 /** Given a Symbol representing a function parameter, see if it or any
801  contained types are varying. If so, issue an error. (This function
802  should only be called for parameters to 'export'ed functions, where
803  varying parameters is illegal.
804  */
805 static void lCheckExportedParameterTypes(const Type *type, const std::string &name, SourcePos pos) {
806  if (lRecursiveCheckValidParamType(type, false) == false) {
807  if (CastType<PointerType>(type))
808  Error(pos,
809  "Varying pointer type parameter \"%s\" is illegal "
810  "in an exported function.",
811  name.c_str());
812  if (CastType<StructType>(type->GetBaseType()))
813  Error(pos,
814  "Struct parameter \"%s\" with vector typed "
815  "member(s) is illegal in an exported function.",
816  name.c_str());
817  else if (CastType<VectorType>(type))
818  Error(pos,
819  "Vector-typed parameter \"%s\" is illegal in an exported "
820  "function.",
821  name.c_str());
822  else
823  Error(pos, "Varying parameter \"%s\" is illegal in an exported function.", name.c_str());
824  }
825 }
826 
827 #ifdef ISPC_NVPTX_ENABLED
828 static void lCheckTaskParameterTypes(const Type *type, const std::string &name, SourcePos pos) {
829  if (g->target->getISA() != Target::NVPTX)
830  return;
831  if (lRecursiveCheckValidParamType(type, false) == false) {
832  if (CastType<VectorType>(type))
833  Error(pos,
834  "Vector-typed parameter \"%s\" is illegal in a task "
835  "function with \"nvptx\" target.",
836  name.c_str());
837  else
838  Error(pos, "Varying parameter \"%s\" is illegal in a task function with \"nvptx\" target.", name.c_str());
839  }
840 }
841 #endif /* ISPC_NVPTX_ENABLED */
842 
843 /** Given a function type, loop through the function parameters and see if
844  any are StructTypes. If so, issue an error; this is currently broken
845  (https://github.com/ispc/ispc/issues/3).
846  */
847 static void lCheckForStructParameters(const FunctionType *ftype, SourcePos pos) {
848  for (int i = 0; i < ftype->GetNumParameters(); ++i) {
849  const Type *type = ftype->GetParameterType(i);
850  if (CastType<StructType>(type) != NULL) {
851  Error(pos, "Passing structs to/from application functions by value "
852  "is currently not supported. Use a reference, a const reference, "
853  "a pointer, or a const pointer to the struct instead.");
854  return;
855  }
856  }
857 }
858 
859 /** We've got a declaration for a function to process. This function does
860  all the work of creating the corresponding llvm::Function instance,
861  adding the symbol for the function to the symbol table and doing
862  various sanity checks. This function returns true upon success and
863  false if any errors were encountered.
864  */
865 void Module::AddFunctionDeclaration(const std::string &name, const FunctionType *functionType,
866  StorageClass storageClass, bool isInline, SourcePos pos) {
867  Assert(functionType != NULL);
868 
869  // If a global variable with the same name has already been declared
870  // issue an error.
871  if (symbolTable->LookupVariable(name.c_str()) != NULL) {
872  Error(pos,
873  "Function \"%s\" shadows previously-declared global variable. "
874  "Ignoring this definition.",
875  name.c_str());
876  return;
877  }
878 
879  std::vector<Symbol *> overloadFuncs;
880  symbolTable->LookupFunction(name.c_str(), &overloadFuncs);
881  if (overloadFuncs.size() > 0) {
882  for (unsigned int i = 0; i < overloadFuncs.size(); ++i) {
883  Symbol *overloadFunc = overloadFuncs[i];
884 
885  const FunctionType *overloadType = CastType<FunctionType>(overloadFunc->type);
886  if (overloadType == NULL) {
887  Assert(m->errorCount == 0);
888  continue;
889  }
890 
891  // Check for a redeclaration of a function with the same name
892  // and type. This also hits when we have previously declared
893  // the function and are about to define it.
894  if (Type::Equal(overloadFunc->type, functionType))
895  return;
896 
897  if (functionType->isExported || overloadType->isExported)
898  Error(pos,
899  "Illegal to provide \"export\" qualifier for "
900  "functions with the same name but different types. "
901  "(Previous function declaration (%s:%d).)",
902  overloadFunc->pos.name, overloadFunc->pos.first_line);
903 
904  // If all of the parameter types match but the return type is
905  // different, return an error--overloading by return type isn't
906  // allowed.
907  const FunctionType *ofType = CastType<FunctionType>(overloadFunc->type);
908  Assert(ofType != NULL);
909  if (ofType->GetNumParameters() == functionType->GetNumParameters()) {
910  int i;
911  for (i = 0; i < functionType->GetNumParameters(); ++i) {
912  if (Type::Equal(ofType->GetParameterType(i), functionType->GetParameterType(i)) == false)
913  break;
914  }
915  if (i == functionType->GetNumParameters()) {
916  std::string thisRetType = functionType->GetReturnTypeString();
917  std::string otherRetType = ofType->GetReturnTypeString();
918  Error(pos,
919  "Illegal to overload function by return "
920  "type only. This function returns \"%s\" while "
921  "previous declaration at %s:%d returns \"%s\".",
922  thisRetType.c_str(), overloadFunc->pos.name, overloadFunc->pos.first_line,
923  otherRetType.c_str());
924  return;
925  }
926  }
927  }
928  }
929 
930  if (storageClass == SC_EXTERN_C) {
931  // Make sure the user hasn't supplied both an 'extern "C"' and a
932  // 'task' qualifier with the function
933  if (functionType->isTask) {
934  Error(pos,
935  "\"task\" qualifier is illegal with C-linkage extern "
936  "function \"%s\". Ignoring this function.",
937  name.c_str());
938  return;
939  }
940 
941  std::vector<Symbol *> funcs;
942  symbolTable->LookupFunction(name.c_str(), &funcs);
943  if (funcs.size() > 0) {
944  if (funcs.size() > 1) {
945  // Multiple functions with this name have already been declared;
946  // can't overload here
947  Error(pos,
948  "Can't overload extern \"C\" function \"%s\"; "
949  "%d functions with the same name have already been declared.",
950  name.c_str(), (int)funcs.size());
951  return;
952  }
953 
954  // One function with the same name has been declared; see if it
955  // has the same type as this one, in which case it's ok.
956  if (Type::Equal(funcs[0]->type, functionType))
957  return;
958  else {
959  Error(pos, "Can't overload extern \"C\" function \"%s\".", name.c_str());
960  return;
961  }
962  }
963  }
964 
965  // Get the LLVM FunctionType
966  bool disableMask = (storageClass == SC_EXTERN_C);
967  llvm::FunctionType *llvmFunctionType = functionType->LLVMFunctionType(g->ctx, disableMask);
968  if (llvmFunctionType == NULL)
969  return;
970 
971  // And create the llvm::Function
972  llvm::GlobalValue::LinkageTypes linkage = (storageClass == SC_STATIC || isInline)
973  ? llvm::GlobalValue::InternalLinkage
974  : llvm::GlobalValue::ExternalLinkage;
975 
976  std::string functionName = name;
977  if (storageClass != SC_EXTERN_C) {
978  functionName += functionType->Mangle();
979  // If we treat generic as smth, we should have appropriate mangling
981  if (g->target->getISA() == Target::GENERIC && !g->target->getTreatGenericAsSmth().empty())
982  functionName += g->target->getTreatGenericAsSmth();
983  else
984  functionName += g->target->GetISAString();
985  }
986  }
987  llvm::Function *function = llvm::Function::Create(llvmFunctionType, linkage, functionName.c_str(), module);
988 
989 #ifdef ISPC_IS_WINDOWS
990  // Make export functions callable from DLLS.
991  if ((g->dllExport) && (storageClass != SC_STATIC)) {
992  function->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
993  }
994 #endif
995 
996  // Set function attributes: we never throw exceptions
997  function->setDoesNotThrow();
998  if (storageClass != SC_EXTERN_C && isInline)
999 #ifdef LLVM_3_2
1000  function->addFnAttr(llvm::Attributes::AlwaysInline);
1001 #else // LLVM 3.3+
1002  function->addFnAttr(llvm::Attribute::AlwaysInline);
1003 #endif
1004 
1005  if (functionType->isTask)
1006 #ifdef ISPC_NVPTX_ENABLED
1007  /* evghenii: fails function verification when "if" executed in nvptx target */
1008  if (g->target->getISA() != Target::NVPTX)
1009 #endif /* ISPC_NVPTX_ENABLED */
1010  // This also applies transitively to members I think?
1011 #if ISPC_LLVM_VERSION < ISPC_LLVM_5_0
1012  function->setDoesNotAlias(1);
1013 #else // LLVM 5.0+
1014  function->addParamAttr(0, llvm::Attribute::NoAlias);
1015 #endif
1016 
1017  g->target->markFuncWithTargetAttr(function);
1018 
1019  // Make sure that the return type isn't 'varying' or vector typed if
1020  // the function is 'export'ed.
1021  if (functionType->isExported && lRecursiveCheckValidParamType(functionType->GetReturnType(), false) == false)
1022  Error(pos,
1023  "Illegal to return a \"varying\" or vector type from "
1024  "exported function \"%s\"",
1025  name.c_str());
1026 
1027  if (functionType->isTask && functionType->GetReturnType()->IsVoidType() == false)
1028  Error(pos, "Task-qualified functions must have void return type.");
1029 
1030 #ifdef ISPC_NVPTX_ENABLED
1031  if (g->target->getISA() == Target::NVPTX && Type::Equal(functionType->GetReturnType(), AtomicType::Void) == false &&
1032  functionType->isExported) {
1033  Error(pos, "Export-qualified functions must have void return type with \"nvptx\" target.");
1034  }
1035 #endif /* ISPC_NVPTX_ENABLED */
1036 
1037  if (functionType->isExported || functionType->isExternC)
1038  lCheckForStructParameters(functionType, pos);
1039 
1040  // Loop over all of the arguments; process default values if present
1041  // and do other checks and parameter attribute setting.
1042  bool seenDefaultArg = false;
1043  int nArgs = functionType->GetNumParameters();
1044  for (int i = 0; i < nArgs; ++i) {
1045  const Type *argType = functionType->GetParameterType(i);
1046  const std::string &argName = functionType->GetParameterName(i);
1047  Expr *defaultValue = functionType->GetParameterDefault(i);
1048  const SourcePos &argPos = functionType->GetParameterSourcePos(i);
1049 
1050  // If the function is exported, make sure that the parameter
1051  // doesn't have any funky stuff going on in it.
1052  // JCB nomosoa - Varying is now a-ok.
1053  if (functionType->isExported) {
1054  lCheckExportedParameterTypes(argType, argName, argPos);
1055  }
1056 
1057 #ifdef ISPC_NVPTX_ENABLED
1058  if (functionType->isTask) {
1059  lCheckTaskParameterTypes(argType, argName, argPos);
1060  }
1061 #endif /* ISPC_NVPTX_ENABLED */
1062 
1063  // ISPC assumes that no pointers alias. (It should be possible to
1064  // specify when this is not the case, but this should be the
1065  // default.) Set parameter attributes accordingly. (Only for
1066  // uniform pointers, since varying pointers are int vectors...)
1067  if (!functionType->isTask && ((CastType<PointerType>(argType) != NULL && argType->IsUniformType() &&
1068  // Exclude SOA argument because it is a pair {struct *, int}
1069  // instead of pointer
1070  !CastType<PointerType>(argType)->IsSlice()) ||
1071 
1072  CastType<ReferenceType>(argType) != NULL)) {
1073 
1074 #if ISPC_LLVM_VERSION < ISPC_LLVM_5_0
1075  // NOTE: LLVM indexes function parameters starting from 1.
1076  // This is unintuitive.
1077  function->setDoesNotAlias(i + 1);
1078 #else // LLVM 5.0+
1079  function->addParamAttr(i, llvm::Attribute::NoAlias);
1080 #endif
1081 #if 0
1082  int align = 4 * RoundUpPow2(g->target->nativeVectorWidth);
1083  function->addAttribute(i+1, llvm::Attribute::constructAlignmentFromInt(align));
1084 #endif
1085  }
1086 
1087  if (symbolTable->LookupFunction(argName.c_str()))
1088  Warning(argPos,
1089  "Function parameter \"%s\" shadows a function "
1090  "declared in global scope.",
1091  argName.c_str());
1092 
1093  if (defaultValue != NULL)
1094  seenDefaultArg = true;
1095  else if (seenDefaultArg) {
1096  // Once one parameter has provided a default value, then all of
1097  // the following ones must have them as well.
1098  Error(argPos,
1099  "Parameter \"%s\" is missing default: all "
1100  "parameters after the first parameter with a default value "
1101  "must have default values as well.",
1102  argName.c_str());
1103  }
1104  }
1105 
1106  // If llvm gave us back a Function * with a different name than the one
1107  // we asked for, then there's already a function with that same
1108  // (mangled) name in the llvm::Module. In that case, erase the one we
1109  // tried to add and just work with the one it already had.
1110  if (function->getName() != functionName) {
1111  function->eraseFromParent();
1112  function = module->getFunction(functionName);
1113  }
1114 
1115  // Finally, we know all is good and we can add the function to the
1116  // symbol table
1117  Symbol *funSym = new Symbol(name, pos, functionType, storageClass);
1118  funSym->function = function;
1119  bool ok = symbolTable->AddFunction(funSym);
1120  Assert(ok);
1121 }
1122 
1123 void Module::AddFunctionDefinition(const std::string &name, const FunctionType *type, Stmt *code) {
1124  Symbol *sym = symbolTable->LookupFunction(name.c_str(), type);
1125  if (sym == NULL || code == NULL) {
1126  Assert(m->errorCount > 0);
1127  return;
1128  }
1129 
1130  sym->pos = code->pos;
1131 
1132  // FIXME: because we encode the parameter names in the function type,
1133  // we need to override the function type here in case the function had
1134  // earlier been declared with anonymous parameter names but is now
1135  // defined with actual names. This is yet another reason we shouldn't
1136  // include the names in FunctionType...
1137  sym->type = type;
1138 
1139  ast->AddFunction(sym, code);
1140 }
1141 
1142 void Module::AddExportedTypes(const std::vector<std::pair<const Type *, SourcePos>> &types) {
1143  for (int i = 0; i < (int)types.size(); ++i) {
1144  if (CastType<StructType>(types[i].first) == NULL && CastType<VectorType>(types[i].first) == NULL &&
1145  CastType<EnumType>(types[i].first) == NULL)
1146  Error(types[i].second,
1147  "Only struct, vector, and enum types, "
1148  "not \"%s\", are allowed in type export lists.",
1149  types[i].first->GetString().c_str());
1150  else
1151  exportedTypes.push_back(types[i]);
1152  }
1153 }
1154 
1155 bool Module::writeOutput(OutputType outputType, OutputFlags flags, const char *outFileName, const char *includeFileName,
1156  const char *sourceFileName, DispatchHeaderInfo *DHI) {
1157  if (diBuilder && (outputType != Header) && (outputType != Deps))
1159 
1160 #if ISPC_LLVM_VERSION >= ISPC_LLVM_3_4 /* 3.4+ */
1161  // In LLVM_3_4 after r195494 and r195504 revisions we should pass
1162  // "Debug Info Version" constant to the module. LLVM will ignore
1163  // our Debug Info metadata without it.
1164  if (g->generateDebuggingSymbols == true) {
1165  module->addModuleFlag(llvm::Module::Warning, "Debug Info Version", llvm::DEBUG_METADATA_VERSION);
1166  }
1167 #endif
1168 
1169  // SIC! (verifyModule() == TRUE) means "failed", see llvm-link code.
1170  if ((outputType != Header) && (outputType != Deps) && (outputType != HostStub) && (outputType != DevStub) &&
1171  module && llvm::verifyModule(*module))
1172  FATAL("Resulting module verification failed!");
1173 
1174  if (outFileName) {
1175  // First, issue a warning if the output file suffix and the type of
1176  // file being created seem to mismatch. This can help catch missing
1177  // command-line arguments specifying the output file type.
1178  const char *suffix = strrchr(outFileName, '.');
1179  if (suffix != NULL) {
1180  ++suffix;
1181  const char *fileType = NULL;
1182  switch (outputType) {
1183  case Asm:
1184 #ifdef ISPC_NVPTX_ENABLED
1185  if (g->target->getISA() == Target::NVPTX) {
1186  if (strcasecmp(suffix, "ptx"))
1187  fileType = "assembly";
1188  } else
1189 #endif /* ISPC_NVPTX_ENABLED */
1190  if (strcasecmp(suffix, "s"))
1191  fileType = "assembly";
1192  break;
1193  case Bitcode:
1194 #ifdef ISPC_NVPTX_ENABLED
1195  if (g->target->getISA() == Target::NVPTX) {
1196  if (strcasecmp(suffix, "ll"))
1197  fileType = "LLVM assembly";
1198  } else
1199 #endif /* ISPC_NVPTX_ENABLED */
1200  if (strcasecmp(suffix, "bc"))
1201  fileType = "LLVM bitcode";
1202  break;
1203  case Object:
1204  if (strcasecmp(suffix, "o") && strcasecmp(suffix, "obj"))
1205  fileType = "object";
1206  break;
1207  case CXX:
1208  if (strcasecmp(suffix, "c") && strcasecmp(suffix, "cc") && strcasecmp(suffix, "c++") &&
1209  strcasecmp(suffix, "cxx") && strcasecmp(suffix, "cpp"))
1210  fileType = "c++";
1211  break;
1212  case Header:
1213  if (strcasecmp(suffix, "h") && strcasecmp(suffix, "hh") && strcasecmp(suffix, "hpp"))
1214  fileType = "header";
1215  break;
1216  case Deps:
1217  break;
1218  case DevStub:
1219  if (strcasecmp(suffix, "c") && strcasecmp(suffix, "cc") && strcasecmp(suffix, "c++") &&
1220  strcasecmp(suffix, "cxx") && strcasecmp(suffix, "cpp"))
1221  fileType = "dev-side offload stub";
1222  break;
1223  case HostStub:
1224  if (strcasecmp(suffix, "c") && strcasecmp(suffix, "cc") && strcasecmp(suffix, "c++") &&
1225  strcasecmp(suffix, "cxx") && strcasecmp(suffix, "cpp"))
1226  fileType = "host-side offload stub";
1227  break;
1228  default:
1229  Assert(0 /* swtich case not handled */);
1230  return 1;
1231  }
1232  if (fileType != NULL)
1233  Warning(SourcePos(),
1234  "Emitting %s file, but filename \"%s\" "
1235  "has suffix \"%s\"?",
1236  fileType, outFileName, suffix);
1237  }
1238  }
1239 
1240  if (outputType == Header) {
1241  if (DHI)
1242  return writeDispatchHeader(DHI);
1243  else
1244  return writeHeader(outFileName);
1245  } else if (outputType == Deps)
1246  return writeDeps(outFileName, 0 != (flags & GenerateMakeRuleForDeps), includeFileName, sourceFileName);
1247  else if (outputType == HostStub)
1248  return writeHostStub(outFileName);
1249  else if (outputType == DevStub)
1250  return writeDevStub(outFileName);
1251  else if (outputType == Bitcode)
1252  return writeBitcode(module, outFileName);
1253  else if (outputType == CXX) {
1254  if (g->target->getISA() != Target::GENERIC) {
1255  Error(SourcePos(), "Only \"generic-*\" targets can be used with "
1256  "C++ emission.");
1257  return false;
1258  }
1259  extern bool WriteCXXFile(llvm::Module * module, const char *fn, int vectorWidth, const char *includeName);
1260  return WriteCXXFile(module, outFileName, g->target->getVectorWidth(), includeFileName);
1261  } else
1262  return writeObjectFileOrAssembly(outputType, outFileName);
1263 }
1264 
1265 #ifdef ISPC_NVPTX_ENABLED
1266 typedef std::vector<std::string> vecString_t;
1267 static vecString_t lSplitString(const std::string &s) {
1268  std::stringstream ss(s);
1269  std::istream_iterator<std::string> begin(ss);
1270  std::istream_iterator<std::string> end;
1271  return vecString_t(begin, end);
1272 }
1273 
1274 static void lFixAttributes(const vecString_t &src, vecString_t &dst) {
1275  dst.clear();
1276 
1277  std::vector<std::pair<int, int>> attributePos;
1278 
1279  typedef std::map<std::string, std::string> attributeMap_t;
1280  attributeMap_t attributeMap;
1281 
1282 #ifdef ISPC_NVPTX_NVVM_OLD /* guard for NVVM from CUDA TK < 7.0 */
1283  for (vecString_t::const_iterator it = src.begin(); it != src.end(); it++) {
1284  const vecString_t words = lSplitString(*it);
1285  if (!words.empty() && words[0] == "attributes" && words[1][0] == '#') {
1286  const int nWords = words.size();
1287  assert(nWords > 3);
1288  assert(words[2] == "=");
1289  assert(words[3] == "{");
1290  assert(words[nWords - 1] == "}");
1291  std::string attributes;
1292  for (int w = 4; w < nWords - 1; w++)
1293  attributes += words[w] + " ";
1294  attributeMap[words[1]] = attributes;
1295  }
1296  }
1297 #endif
1298 
1299  for (vecString_t::const_iterator it = src.begin(); it != src.end(); it++) {
1300  vecString_t words = lSplitString(*it);
1301  /* evghenii: is there a cleaner way to set target datalayout for ptx ? */
1302  if (words.size() > 1 && (words[0] == "target" && words[1] == "datalayout")) {
1303  std::string s = "target datalayout = ";
1304  s += '"';
1305  s += "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v16:16:16-v32:32:32-v64:"
1306  "64:64-v128:128:128-n16:32:64";
1307  s += '"';
1308  dst.push_back(s);
1309  continue;
1310  }
1311  if (!words.empty() && words[0] == "attributes")
1312  continue;
1313  std::string s;
1314  std::map<std::string, std::string> attributeSet;
1315 #ifdef ISPC_NVPTX_NVVM_OLD /* guard for NVVM from CUDA TK < 7.0 */
1316  /* this attributed cannot be used in function parameters, so remove them */
1317  attributeSet["readnone"] = " ";
1318  attributeSet["readonly"] = " ";
1319  attributeSet["readnone,"] = ",";
1320  attributeSet["readonly,"] = ",";
1321 #endif
1322 
1323  for (vecString_t::iterator w = words.begin(); w != words.end(); w++) {
1324  if (attributeSet.find(*w) != attributeSet.end())
1325  *w = attributeSet[*w];
1326 
1327  if ((*w)[0] == '#') {
1328  attributeMap_t::iterator m = attributeMap.find(*w);
1329  if (m != attributeMap.end())
1330  *w = attributeMap[*w];
1331  }
1332  s += *w + " ";
1333  }
1334  dst.push_back(s);
1335  }
1336 }
1337 #endif /* ISPC_NVPTX_ENABLED */
1338 
1339 bool Module::writeBitcode(llvm::Module *module, const char *outFileName) {
1340  // Get a file descriptor corresponding to where we want the output to
1341  // go. If we open it, it'll be closed by the llvm::raw_fd_ostream
1342  // destructor.
1343  int fd;
1344  if (!strcmp(outFileName, "-"))
1345  fd = 1; // stdout
1346  else {
1347  int flags = O_CREAT | O_WRONLY | O_TRUNC;
1348 #ifdef ISPC_IS_WINDOWS
1349  flags |= O_BINARY;
1350  fd = _open(outFileName, flags, 0644);
1351 #else
1352  fd = open(outFileName, flags, 0644);
1353 #endif // ISPC_IS_WINDOWS
1354  if (fd == -1) {
1355  perror(outFileName);
1356  return false;
1357  }
1358  }
1359 
1360  llvm::raw_fd_ostream fos(fd, (fd != 1), false);
1361 #ifdef ISPC_NVPTX_ENABLED
1362  if (g->target->getISA() == Target::NVPTX) {
1363  /* when using "nvptx" target, emit patched/hacked assembly
1364  * NVPTX only accepts 3.2-style LLVM assembly, where attributes
1365  * must be inlined, rather then referenced by #attribute_d
1366  * As soon as NVVM support 3.3,3.4 style assembly this fix won't be needed
1367  */
1368  const std::string dl_string = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-"
1369  "v16:16:16-v32:32:32-v64:64:64-v128:128:128-n16:32:64";
1370  module->setDataLayout(dl_string);
1371 
1372  std::string s;
1373  llvm::raw_string_ostream out(s);
1374 #if ISPC_LLVM_VERSION >= ISPC_LLVM_3_5 /* 3.5+ */
1375  std::unique_ptr<llvm::AssemblyAnnotationWriter> Annotator;
1376 #else
1377  llvm::OwningPtr<llvm::AssemblyAnnotationWriter> Annotator;
1378 #endif
1379  module->print(out, Annotator.get());
1380  std::istringstream iss(s);
1381 
1382  vecString_t input, output;
1383  while (std::getline(iss, s))
1384  input.push_back(s);
1385  output = input;
1386 
1387 #if ISPC_LLVM_VERSION >= ISPC_LLVM_3_3 /* 3.3+ */
1388  /* do not fix attributed with LLVM 3.2, everything is fine there */
1389  lFixAttributes(input, output);
1390 #endif
1391 
1392  for (vecString_t::iterator it = output.begin(); it != output.end(); it++) {
1393  *it += "\n";
1394  fos << *it;
1395  }
1396  } else
1397 #endif /* ISPC_NVPTX_ENABLED */
1398 #if ISPC_LLVM_VERSION < ISPC_LLVM_7_0
1399  llvm::WriteBitcodeToFile(module, fos);
1400 #else
1401  llvm::WriteBitcodeToFile(*module, fos);
1402 #endif
1403 
1404  return true;
1405 }
1406 
1407 bool Module::writeObjectFileOrAssembly(OutputType outputType, const char *outFileName) {
1408  llvm::TargetMachine *targetMachine = g->target->GetTargetMachine();
1409  return writeObjectFileOrAssembly(targetMachine, module, outputType, outFileName);
1410 }
1411 
1412 bool Module::writeObjectFileOrAssembly(llvm::TargetMachine *targetMachine, llvm::Module *module, OutputType outputType,
1413  const char *outFileName) {
1414  // Figure out if we're generating object file or assembly output, and
1415  // set binary output for object files
1416  llvm::TargetMachine::CodeGenFileType fileType =
1417  (outputType == Object) ? llvm::TargetMachine::CGFT_ObjectFile : llvm::TargetMachine::CGFT_AssemblyFile;
1418  bool binary = (fileType == llvm::TargetMachine::CGFT_ObjectFile);
1419 #if ISPC_LLVM_VERSION <= ISPC_LLVM_3_3 // 3.2, 3.3
1420  unsigned int flags = binary ? llvm::raw_fd_ostream::F_Binary : 0;
1421 #elif ISPC_LLVM_VERSION == ISPC_LLVM_3_4 // 3.4
1422  llvm::sys::fs::OpenFlags flags = binary ? llvm::sys::fs::F_Binary : llvm::sys::fs::F_None;
1423 #else // LLVM 3.5+
1424  llvm::sys::fs::OpenFlags flags = binary ? llvm::sys::fs::F_None : llvm::sys::fs::F_Text;
1425 
1426 #endif
1427 
1428 #if ISPC_LLVM_VERSION <= ISPC_LLVM_3_5
1429  std::string error;
1430 #else // LLVM 3.6+
1431  std::error_code error;
1432 #endif
1433 
1434 #if ISPC_LLVM_VERSION <= ISPC_LLVM_3_6
1435  llvm::tool_output_file *of = new llvm::tool_output_file(outFileName, error, flags);
1436 #elif ISPC_LLVM_VERSION <= ISPC_LLVM_5_0 // LLVM 3.7-5.0
1437  std::unique_ptr<llvm::tool_output_file> of(new llvm::tool_output_file(outFileName, error, flags));
1438 #else // LLVM 6.0+
1439  std::unique_ptr<llvm::ToolOutputFile> of(new llvm::ToolOutputFile(outFileName, error, flags));
1440 #endif
1441 
1442 #if ISPC_LLVM_VERSION <= ISPC_LLVM_3_5
1443  if (error.size()) {
1444 #else // LLVM 3.6+
1445  if (error) {
1446 #endif
1447 
1448  fprintf(stderr, "Error opening output file \"%s\".\n", outFileName);
1449  return false;
1450  }
1451 
1452 #if ISPC_LLVM_VERSION <= ISPC_LLVM_3_6
1453  llvm::PassManager pm;
1454 #else // LLVM 3.7+
1455  llvm::legacy::PassManager pm;
1456 #endif
1457 #if ISPC_LLVM_VERSION <= ISPC_LLVM_3_4 // 3.2, 3.3, 3.4
1458  pm.add(new llvm::DataLayout(*g->target->getDataLayout()));
1459 #elif ISPC_LLVM_VERSION == ISPC_LLVM_3_5 // 3.5
1460  pm.add(new llvm::DataLayoutPass(*g->target->getDataLayout()));
1461 #elif ISPC_LLVM_VERSION == ISPC_LLVM_3_6 // 3.6
1462 llvm::DataLayoutPass *dlp = new llvm::DataLayoutPass();
1463 dlp->doInitialization(*module);
1464 pm.add(dlp);
1465 #endif // LLVM 3.7+ doesn't have DataLayoutPass anymore.
1466 
1467  {
1468 #if ISPC_LLVM_VERSION <= ISPC_LLVM_3_6
1469  llvm::formatted_raw_ostream fos(of->os());
1470 #else // LLVM 3.7+
1471  llvm::raw_fd_ostream &fos(of->os());
1472 #endif
1473 #if ISPC_LLVM_VERSION <= ISPC_LLVM_6_0
1474  if (targetMachine->addPassesToEmitFile(pm, fos, fileType)) {
1475  fprintf(stderr, "Fatal error adding passes to emit object file!");
1476  exit(1);
1477  }
1478 #else // LLVM 7.0+
1479  // Third parameter is for generation of .dwo file, which is separate DWARF
1480  // file for ELF targets. We don't support it currently.
1481  if (targetMachine->addPassesToEmitFile(pm, fos, nullptr, fileType)) {
1482  fprintf(stderr, "Fatal error adding passes to emit object file!");
1483  exit(1);
1484  }
1485 #endif
1486 
1487  // Finally, run the passes to emit the object file/assembly
1488  pm.run(*module);
1489 
1490  // Success; tell tool_output_file to keep the final output file.
1491  of->keep();
1492  }
1493 #if ISPC_LLVM_VERSION <= ISPC_LLVM_3_6
1494  delete of;
1495 #endif // LLVM 3.7+
1496  return true;
1497 }
1498 
1499 /** Given a pointer to an element of a structure, see if it is a struct
1500  type or an array of a struct type. If so, return a pointer to the
1501  underlying struct type. */
1502 static const StructType *lGetElementStructType(const Type *t) {
1503  const StructType *st = CastType<StructType>(t);
1504  if (st != NULL)
1505  return st;
1506 
1507  const ArrayType *at = CastType<ArrayType>(t);
1508  if (at != NULL)
1509  return lGetElementStructType(at->GetElementType());
1510 
1511  return NULL;
1512 }
1513 
1514 static bool lContainsPtrToVarying(const StructType *st) {
1515  int numElts = st->GetElementCount();
1516 
1517  for (int j = 0; j < numElts; ++j) {
1518  const Type *t = st->GetElementType(j);
1519 
1520  if (t->IsVaryingType())
1521  return true;
1522  }
1523 
1524  return false;
1525 }
1526 
1527 /** Emits a declaration for the given struct to the given file. This
1528  function first makes sure that declarations for any structs that are
1529  (recursively) members of this struct are emitted first.
1530  */
1531 static void lEmitStructDecl(const StructType *st, std::vector<const StructType *> *emittedStructs, FILE *file,
1532  bool emitUnifs = true) {
1533 
1534  // if we're emitting this for a generic dispatch header file and it's
1535  // struct that only contains uniforms, don't bother if we're emitting uniforms
1536  if (!emitUnifs && !lContainsPtrToVarying(st)) {
1537  return;
1538  }
1539 
1540  // Has this struct type already been declared? (This happens if it's a
1541  // member of another struct for which we emitted a declaration
1542  // previously.)
1543  for (int i = 0; i < (int)emittedStructs->size(); ++i)
1544  if (Type::EqualIgnoringConst(st, (*emittedStructs)[i]))
1545  return;
1546 
1547  // Otherwise first make sure any contained structs have been declared.
1548  for (int i = 0; i < st->GetElementCount(); ++i) {
1549  const StructType *elementStructType = lGetElementStructType(st->GetElementType(i));
1550  if (elementStructType != NULL)
1551  lEmitStructDecl(elementStructType, emittedStructs, file, emitUnifs);
1552  }
1553 
1554  // And now it's safe to declare this one
1555  emittedStructs->push_back(st);
1556 
1557  fprintf(file, "#ifndef __ISPC_STRUCT_%s__\n", st->GetCStructName().c_str());
1558  fprintf(file, "#define __ISPC_STRUCT_%s__\n", st->GetCStructName().c_str());
1559 
1560  char sSOA[48];
1561  bool pack, needsAlign = false;
1562  llvm::Type *stype = st->LLVMType(g->ctx);
1563  const llvm::DataLayout *DL = g->target->getDataLayout();
1564 
1565  if (!(pack = llvm::dyn_cast<llvm::StructType>(stype)->isPacked()))
1566  for (int i = 0; !needsAlign && (i < st->GetElementCount()); ++i) {
1567  const Type *ftype = st->GetElementType(i)->GetAsNonConstType();
1568  needsAlign |= ftype->IsVaryingType() && (CastType<StructType>(ftype) == NULL);
1569  }
1570  if (st->GetSOAWidth() > 0)
1571  // This has to match the naming scheme in
1572  // StructType::GetCDeclaration().
1573  snprintf(sSOA, sizeof(sSOA), "_SOA%d", st->GetSOAWidth());
1574  else
1575  *sSOA = '\0';
1576  if (!needsAlign)
1577  fprintf(file, "%sstruct %s%s {\n", (pack) ? "packed " : "", st->GetCStructName().c_str(), sSOA);
1578  else {
1579  unsigned uABI = DL->getABITypeAlignment(stype);
1580  fprintf(file, "__ISPC_ALIGNED_STRUCT__(%u) %s%s {\n", uABI, st->GetCStructName().c_str(), sSOA);
1581  }
1582  for (int i = 0; i < st->GetElementCount(); ++i) {
1583  const Type *ftype = st->GetElementType(i)->GetAsNonConstType();
1584  std::string d = ftype->GetCDeclaration(st->GetElementName(i));
1585 
1586  fprintf(file, " ");
1587  if (needsAlign && ftype->IsVaryingType() && (CastType<StructType>(ftype) == NULL)) {
1588  unsigned uABI = DL->getABITypeAlignment(ftype->LLVMType(g->ctx));
1589  fprintf(file, "__ISPC_ALIGN__(%u) ", uABI);
1590  }
1591  // Don't expand arrays, pointers and structures:
1592  // their insides will be expanded automatically.
1593  if (!ftype->IsArrayType() && !ftype->IsPointerType() && ftype->IsVaryingType() &&
1594  (CastType<StructType>(ftype) == NULL)) {
1595  fprintf(file, "%s[%d];\n", d.c_str(), g->target->getVectorWidth());
1596  } else {
1597  fprintf(file, "%s;\n", d.c_str());
1598  }
1599  }
1600  fprintf(file, "};\n");
1601  fprintf(file, "#endif\n\n");
1602 }
1603 
1604 /** Given a set of structures that we want to print C declarations of in a
1605  header file, emit their declarations.
1606  */
1607 static void lEmitStructDecls(std::vector<const StructType *> &structTypes, FILE *file, bool emitUnifs = true) {
1608  std::vector<const StructType *> emittedStructs;
1609 
1610  fprintf(file, "\n#ifndef __ISPC_ALIGN__\n"
1611  "#if defined(__clang__) || !defined(_MSC_VER)\n"
1612  "// Clang, GCC, ICC\n"
1613  "#define __ISPC_ALIGN__(s) __attribute__((aligned(s)))\n"
1614  "#define __ISPC_ALIGNED_STRUCT__(s) struct __ISPC_ALIGN__(s)\n"
1615  "#else\n"
1616  "// Visual Studio\n"
1617  "#define __ISPC_ALIGN__(s) __declspec(align(s))\n"
1618  "#define __ISPC_ALIGNED_STRUCT__(s) __ISPC_ALIGN__(s) struct\n"
1619  "#endif\n"
1620  "#endif\n\n");
1621 
1622  for (unsigned int i = 0; i < structTypes.size(); ++i)
1623  lEmitStructDecl(structTypes[i], &emittedStructs, file, emitUnifs);
1624 }
1625 
1626 /** Emit C declarations of enumerator types to the generated header file.
1627  */
1628 static void lEmitEnumDecls(const std::vector<const EnumType *> &enumTypes, FILE *file) {
1629  if (enumTypes.size() == 0)
1630  return;
1631 
1632  fprintf(file, "///////////////////////////////////////////////////////////////////////////\n");
1633  fprintf(file, "// Enumerator types with external visibility from ispc code\n");
1634  fprintf(file, "///////////////////////////////////////////////////////////////////////////\n\n");
1635 
1636  for (unsigned int i = 0; i < enumTypes.size(); ++i) {
1637  fprintf(file, "#ifndef __ISPC_ENUM_%s__\n", enumTypes[i]->GetEnumName().c_str());
1638  fprintf(file, "#define __ISPC_ENUM_%s__\n", enumTypes[i]->GetEnumName().c_str());
1639  std::string declaration = enumTypes[i]->GetCDeclaration("");
1640  fprintf(file, "%s {\n", declaration.c_str());
1641 
1642  // Print the individual enumerators
1643  for (int j = 0; j < enumTypes[i]->GetEnumeratorCount(); ++j) {
1644  const Symbol *e = enumTypes[i]->GetEnumerator(j);
1645  Assert(e->constValue != NULL);
1646  unsigned int enumValue;
1647  int count = e->constValue->GetValues(&enumValue);
1648  Assert(count == 1);
1649 
1650  // Always print an initializer to set the value. We could be
1651  // 'clever' here and detect whether the implicit value given by
1652  // one plus the previous enumerator value (or zero, for the
1653  // first enumerator) is the same as the value stored with the
1654  // enumerator, though that doesn't seem worth the trouble...
1655  fprintf(file, " %s = %d%c\n", e->name.c_str(), enumValue,
1656  (j < enumTypes[i]->GetEnumeratorCount() - 1) ? ',' : ' ');
1657  }
1658  fprintf(file, "};\n");
1659  fprintf(file, "#endif\n\n");
1660  }
1661 }
1662 
1663 /** Print declarations of VectorTypes used in 'export'ed parts of the
1664  program in the header file.
1665  */
1666 static void lEmitVectorTypedefs(const std::vector<const VectorType *> &types, FILE *file) {
1667  if (types.size() == 0)
1668  return;
1669 
1670  fprintf(file, "///////////////////////////////////////////////////////////////////////////\n");
1671  fprintf(file, "// Vector types with external visibility from ispc code\n");
1672  fprintf(file, "///////////////////////////////////////////////////////////////////////////\n\n");
1673 
1674  for (unsigned int i = 0; i < types.size(); ++i) {
1675  std::string baseDecl;
1676  const VectorType *vt = types[i]->GetAsNonConstType();
1677  if (!vt->IsUniformType())
1678  // Varying stuff shouldn't be visibile to / used by the
1679  // application, so at least make it not simple to access it by
1680  // not declaring the type here...
1681  continue;
1682 
1683  int size = vt->GetElementCount();
1684 
1685  llvm::Type *ty = vt->LLVMType(g->ctx);
1686  int align = g->target->getDataLayout()->getABITypeAlignment(ty);
1687  baseDecl = vt->GetBaseType()->GetCDeclaration("");
1688  fprintf(file, "#ifndef __ISPC_VECTOR_%s%d__\n", baseDecl.c_str(), size);
1689  fprintf(file, "#define __ISPC_VECTOR_%s%d__\n", baseDecl.c_str(), size);
1690  fprintf(file, "#ifdef _MSC_VER\n__declspec( align(%d) ) ", align);
1691  fprintf(file, "struct %s%d { %s v[%d]; };\n", baseDecl.c_str(), size, baseDecl.c_str(), size);
1692  fprintf(file, "#else\n");
1693  fprintf(file, "struct %s%d { %s v[%d]; } __attribute__ ((aligned(%d)));\n", baseDecl.c_str(), size,
1694  baseDecl.c_str(), size, align);
1695  fprintf(file, "#endif\n");
1696  fprintf(file, "#endif\n\n");
1697  }
1698  fprintf(file, "\n");
1699 }
1700 
1701 /** Add the given type to the vector, if that type isn't already in there.
1702  */
1703 template <typename T> static void lAddTypeIfNew(const Type *type, std::vector<const T *> *exportedTypes) {
1704  type = type->GetAsNonConstType();
1705 
1706  // Linear search, so this ends up being n^2. It's unlikely this will
1707  // matter in practice, though.
1708  for (unsigned int i = 0; i < exportedTypes->size(); ++i)
1709  if (Type::Equal((*exportedTypes)[i], type))
1710  return;
1711 
1712  const T *castType = CastType<T>(type);
1713  Assert(castType != NULL);
1714  exportedTypes->push_back(castType);
1715 }
1716 
1717 /** Given an arbitrary type that appears in the app/ispc interface, add it
1718  to an appropriate vector if it is a struct, enum, or short vector type.
1719  Then, if it's a struct, recursively process its members to do the same.
1720  */
1721 static void lGetExportedTypes(const Type *type, std::vector<const StructType *> *exportedStructTypes,
1722  std::vector<const EnumType *> *exportedEnumTypes,
1723  std::vector<const VectorType *> *exportedVectorTypes) {
1724  const ArrayType *arrayType = CastType<ArrayType>(type);
1725  const StructType *structType = CastType<StructType>(type);
1726  const FunctionType *ftype = CastType<FunctionType>(type);
1727 
1728  if (CastType<ReferenceType>(type) != NULL)
1729  lGetExportedTypes(type->GetReferenceTarget(), exportedStructTypes, exportedEnumTypes, exportedVectorTypes);
1730  else if (CastType<PointerType>(type) != NULL)
1731  lGetExportedTypes(type->GetBaseType(), exportedStructTypes, exportedEnumTypes, exportedVectorTypes);
1732  else if (arrayType != NULL)
1733  lGetExportedTypes(arrayType->GetElementType(), exportedStructTypes, exportedEnumTypes, exportedVectorTypes);
1734  else if (structType != NULL) {
1735  lAddTypeIfNew(type, exportedStructTypes);
1736  for (int i = 0; i < structType->GetElementCount(); ++i)
1737  lGetExportedTypes(structType->GetElementType(i), exportedStructTypes, exportedEnumTypes,
1738  exportedVectorTypes);
1739  } else if (CastType<UndefinedStructType>(type) != NULL)
1740  // do nothing
1741  ;
1742  else if (CastType<EnumType>(type) != NULL)
1743  lAddTypeIfNew(type, exportedEnumTypes);
1744  else if (CastType<VectorType>(type) != NULL)
1745  lAddTypeIfNew(type, exportedVectorTypes);
1746  else if (ftype != NULL) {
1747  // Handle Return Types
1748  lGetExportedTypes(ftype->GetReturnType(), exportedStructTypes, exportedEnumTypes, exportedVectorTypes);
1749 
1750  // And now the parameter types...
1751  for (int j = 0; j < ftype->GetNumParameters(); ++j)
1752  lGetExportedTypes(ftype->GetParameterType(j), exportedStructTypes, exportedEnumTypes, exportedVectorTypes);
1753  } else
1754  Assert(CastType<AtomicType>(type) != NULL);
1755 }
1756 
1757 /** Given a set of functions, return the set of structure and vector types
1758  present in the parameters to them.
1759  */
1760 static void lGetExportedParamTypes(const std::vector<Symbol *> &funcs,
1761  std::vector<const StructType *> *exportedStructTypes,
1762  std::vector<const EnumType *> *exportedEnumTypes,
1763  std::vector<const VectorType *> *exportedVectorTypes) {
1764  for (unsigned int i = 0; i < funcs.size(); ++i) {
1765  const FunctionType *ftype = CastType<FunctionType>(funcs[i]->type);
1766  // Handle the return type
1767  lGetExportedTypes(ftype->GetReturnType(), exportedStructTypes, exportedEnumTypes, exportedVectorTypes);
1768 
1769  // And now the parameter types...
1770  for (int j = 0; j < ftype->GetNumParameters(); ++j)
1771  lGetExportedTypes(ftype->GetParameterType(j), exportedStructTypes, exportedEnumTypes, exportedVectorTypes);
1772  }
1773 }
1774 
1775 static void lPrintFunctionDeclarations(FILE *file, const std::vector<Symbol *> &funcs, bool useExternC = 1,
1776  bool rewriteForDispatch = false) {
1777  if (useExternC)
1778  fprintf(file, "#if defined(__cplusplus) && (! defined(__ISPC_NO_EXTERN_C) || !__ISPC_NO_EXTERN_C )\nextern "
1779  "\"C\" {\n#endif // __cplusplus\n");
1780  // fprintf(file, "#ifdef __cplusplus\nextern \"C\" {\n#endif // __cplusplus\n");
1781  for (unsigned int i = 0; i < funcs.size(); ++i) {
1782  const FunctionType *ftype = CastType<FunctionType>(funcs[i]->type);
1783  Assert(ftype);
1784  std::string decl;
1785  if (rewriteForDispatch) {
1786  decl = ftype->GetCDeclarationForDispatch(funcs[i]->name);
1787  } else {
1788  decl = ftype->GetCDeclaration(funcs[i]->name);
1789  }
1790  fprintf(file, " extern %s;\n", decl.c_str());
1791  }
1792  if (useExternC)
1793 
1794  fprintf(file, "#if defined(__cplusplus) && (! defined(__ISPC_NO_EXTERN_C) || !__ISPC_NO_EXTERN_C )\n} /* end "
1795  "extern C */\n#endif // __cplusplus\n");
1796  // fprintf(file, "#ifdef __cplusplus\n} /* end extern C */\n#endif // __cplusplus\n");
1797 }
1798 
1799 static bool lIsExported(const Symbol *sym) {
1800  const FunctionType *ft = CastType<FunctionType>(sym->type);
1801  Assert(ft);
1802  return ft->isExported;
1803 }
1804 
1805 static bool lIsExternC(const Symbol *sym) {
1806  const FunctionType *ft = CastType<FunctionType>(sym->type);
1807  Assert(ft);
1808  return ft->isExternC;
1809 }
1810 
1811 static void lUnescapeStringInPlace(std::string &str) {
1812  // There are many more escape sequences, but since this is a path,
1813  // we can get away with only supporting the basic ones (i.e. no
1814  // octal, hexadecimal or unicode values).
1815  for (std::string::iterator it = str.begin(); it != str.end(); ++it) {
1816  size_t pos = it - str.begin();
1817  std::string::iterator next = it + 1;
1818  if (*it == '\\' && next != str.end()) {
1819  switch (*next) {
1820 #define UNESCAPE_SEQ(c, esc) \
1821  case c: \
1822  *it = esc; \
1823  str.erase(next); \
1824  it = str.begin() + pos; \
1825  break
1826  UNESCAPE_SEQ('\'', '\'');
1827  UNESCAPE_SEQ('?', '?');
1828  UNESCAPE_SEQ('\\', '\\');
1829  UNESCAPE_SEQ('a', '\a');
1830  UNESCAPE_SEQ('b', '\b');
1831  UNESCAPE_SEQ('f', '\f');
1832  UNESCAPE_SEQ('n', '\n');
1833  UNESCAPE_SEQ('r', '\r');
1834  UNESCAPE_SEQ('t', '\t');
1835  UNESCAPE_SEQ('v', '\v');
1836 #undef UNESCAPE_SEQ
1837  }
1838  }
1839  }
1840 }
1841 
1842 bool Module::writeDeps(const char *fn, bool generateMakeRule, const char *tn, const char *sn) {
1843  if (fn) // We may be passed nullptr for stdout output.
1844  std::cout << "writing dependencies to file " << fn << std::endl;
1845  FILE *file = fn ? fopen(fn, "w") : stdout;
1846  if (!file) {
1847  perror("fopen");
1848  return false;
1849  }
1850 
1851  if (generateMakeRule) {
1852  fprintf(file, "%s:", tn);
1853  if (sn) // Rules always emit source first.
1854  fprintf(file, " %s \\\n", sn);
1855  std::string unescaped;
1856  for (std::set<std::string>::const_iterator it = registeredDependencies.begin();
1857  it != registeredDependencies.end(); ++it) {
1858  unescaped = *it; // As this is preprocessor output, paths come escaped.
1859  lUnescapeStringInPlace(unescaped);
1860  if (sn && 0 == strcmp(sn, unescaped.c_str())) // If source has been passed, it's already emitted.
1861  continue;
1862  fprintf(file, " %s \\\n", unescaped.c_str());
1863  }
1864  } else {
1865  for (std::set<std::string>::const_iterator it = registeredDependencies.begin();
1866  it != registeredDependencies.end(); ++it)
1867  fprintf(file, "%s\n", it->c_str());
1868  }
1869  fclose(file);
1870  return true;
1871 }
1872 
1873 std::string emitOffloadParamStruct(const std::string &paramStructName, const Symbol *sym, const FunctionType *fct) {
1874  std::stringstream out;
1875  out << "struct " << paramStructName << " {" << std::endl;
1876 
1877  for (int i = 0; i < fct->GetNumParameters(); i++) {
1878  const Type *orgParamType = fct->GetParameterType(i);
1879  if (orgParamType->IsPointerType() || orgParamType->IsArrayType()) {
1880  /* we're passing pointers separately -- no pointers in that struct... */
1881  continue;
1882  }
1883 
1884  // const reference parameters can be passed as copies.
1885  const Type *paramType;
1886  if (orgParamType->IsReferenceType()) {
1887  if (!orgParamType->IsConstType()) {
1888  Error(sym->pos, "When emitting offload-stubs, \"export\"ed functions cannot have non-const "
1889  "reference-type parameters.\n");
1890  }
1891  const ReferenceType *refType = static_cast<const ReferenceType *>(orgParamType);
1892  paramType = refType->GetReferenceTarget()->GetAsNonConstType();
1893  } else {
1894  paramType = orgParamType->GetAsNonConstType();
1895  }
1896  std::string paramName = fct->GetParameterName(i);
1897  std::string paramTypeName = paramType->GetString();
1898 
1899  std::string tmpArgDecl = paramType->GetCDeclaration(paramName);
1900  out << " " << tmpArgDecl << ";" << std::endl;
1901  }
1902 
1903  out << "};" << std::endl;
1904  return out.str();
1905 }
1906 
1907 bool Module::writeDevStub(const char *fn) {
1908  FILE *file = fopen(fn, "w");
1909  if (!file) {
1910  perror("fopen");
1911  return false;
1912  }
1913  fprintf(file, "//\n// %s\n// (device stubs automatically generated by the ispc compiler.)\n", fn);
1914  fprintf(file, "// DO NOT EDIT THIS FILE.\n//\n\n");
1915  fprintf(file, "#include \"ispc/dev/offload.h\"\n\n");
1916 
1917  fprintf(file, "#include <stdint.h>\n\n");
1918 
1919  // Collect single linear arrays of the *exported* functions (we'll
1920  // treat those as "__kernel"s in IVL -- "extern" functions will only
1921  // be used for dev-dev function calls; only "export" functions will
1922  // get exported to the host
1923  std::vector<Symbol *> exportedFuncs;
1924  m->symbolTable->GetMatchingFunctions(lIsExported, &exportedFuncs);
1925 
1926  // Get all of the struct, vector, and enumerant types used as function
1927  // parameters. These vectors may have repeats.
1928  std::vector<const StructType *> exportedStructTypes;
1929  std::vector<const EnumType *> exportedEnumTypes;
1930  std::vector<const VectorType *> exportedVectorTypes;
1931  lGetExportedParamTypes(exportedFuncs, &exportedStructTypes, &exportedEnumTypes, &exportedVectorTypes);
1932 
1933  // And print them
1934  lEmitVectorTypedefs(exportedVectorTypes, file);
1935  lEmitEnumDecls(exportedEnumTypes, file);
1936  lEmitStructDecls(exportedStructTypes, file);
1937 
1938  fprintf(file, "#ifdef __cplusplus\n");
1939  fprintf(file, "namespace ispc {\n");
1940  fprintf(file, "#endif // __cplusplus\n");
1941 
1942  fprintf(file, "\n");
1943  fprintf(file, "///////////////////////////////////////////////////////////////////////////\n");
1944  fprintf(file, "// Functions exported from ispc code\n");
1945  fprintf(file, "// (so the dev stub knows what to call)\n");
1946  fprintf(file, "///////////////////////////////////////////////////////////////////////////\n");
1947  lPrintFunctionDeclarations(file, exportedFuncs, true);
1948 
1949  fprintf(file, "#ifdef __cplusplus\n");
1950  fprintf(file, "}/* end namespace */\n");
1951  fprintf(file, "#endif // __cplusplus\n");
1952 
1953  fprintf(file, "\n");
1954  fprintf(file, "///////////////////////////////////////////////////////////////////////////\n");
1955  fprintf(file, "// actual dev stubs\n");
1956  fprintf(file, "///////////////////////////////////////////////////////////////////////////\n");
1957 
1958  fprintf(file, "// note(iw): due to some linking issues offload stubs *only* work under C++\n");
1959  fprintf(file, "extern \"C\" {\n\n");
1960  for (unsigned int i = 0; i < exportedFuncs.size(); ++i) {
1961  const Symbol *sym = exportedFuncs[i];
1962  Assert(sym);
1963  const FunctionType *fct = CastType<FunctionType>(sym->type);
1964  Assert(fct);
1965 
1966  if (!fct->GetReturnType()->IsVoidType()) {
1967  // Error(sym->pos,"When emitting offload-stubs, \"export\"ed functions cannot have non-void return
1968  // types.\n");
1969  Warning(sym->pos,
1970  "When emitting offload-stubs, ignoring \"export\"ed function with non-void return types.\n");
1971  continue;
1972  }
1973 
1974  // -------------------------------------------------------
1975  // first, emit a struct that holds the parameters
1976  // -------------------------------------------------------
1977  std::string paramStructName = std::string("__ispc_dev_stub_") + sym->name;
1978  std::string paramStruct = emitOffloadParamStruct(paramStructName, sym, fct);
1979  fprintf(file, "%s\n", paramStruct.c_str());
1980  // -------------------------------------------------------
1981  // then, emit a fct stub that unpacks the parameters and pointers
1982  // -------------------------------------------------------
1983  fprintf(file,
1984  "void __ispc_dev_stub_%s(\n"
1985  " uint32_t in_BufferCount,\n"
1986  " void** in_ppBufferPointers,\n"
1987  " uint64_t* in_pBufferLengths,\n"
1988  " void* in_pMiscData,\n"
1989  " uint16_t in_MiscDataLength,\n"
1990  " void* in_pReturnValue,\n"
1991  " uint16_t in_ReturnValueLength)\n",
1992  sym->name.c_str());
1993  fprintf(file, "{\n");
1994  fprintf(file, " struct %s args;\n memcpy(&args,in_pMiscData,sizeof(args));\n", paramStructName.c_str());
1995  std::stringstream funcall;
1996 
1997  funcall << "ispc::" << sym->name << "(";
1998  for (int i = 0; i < fct->GetNumParameters(); i++) {
1999  // get param type and make it non-const, so we can write while unpacking
2000  // const Type *paramType = fct->GetParameterType(i)->GetAsNonConstType();
2001  const Type *paramType; // = fct->GetParameterType(i)->GetAsNonConstType();
2002  const Type *orgParamType = fct->GetParameterType(i);
2003  if (orgParamType->IsReferenceType()) {
2004  if (!orgParamType->IsConstType()) {
2005  Error(sym->pos, "When emitting offload-stubs, \"export\"ed functions cannot have non-const "
2006  "reference-type parameters.\n");
2007  }
2008  const ReferenceType *refType = static_cast<const ReferenceType *>(orgParamType);
2009  paramType = refType->GetReferenceTarget()->GetAsNonConstType();
2010  } else {
2011  paramType = orgParamType->GetAsNonConstType();
2012  }
2013 
2014  std::string paramName = fct->GetParameterName(i);
2015  std::string paramTypeName = paramType->GetString();
2016 
2017  if (i)
2018  funcall << ", ";
2019  std::string tmpArgName = std::string("_") + paramName;
2020  if (paramType->IsPointerType() || paramType->IsArrayType()) {
2021  std::string tmpArgDecl = paramType->GetCDeclaration(tmpArgName);
2022  fprintf(file, " %s;\n", tmpArgDecl.c_str());
2023  fprintf(file, " (void *&)%s = ispc_dev_translate_pointer(*in_ppBufferPointers++);\n",
2024  tmpArgName.c_str());
2025  funcall << tmpArgName;
2026  } else {
2027  funcall << "args." << paramName;
2028  }
2029  }
2030  funcall << ");";
2031  fprintf(file, " %s\n", funcall.str().c_str());
2032  fprintf(file, "}\n\n");
2033  }
2034 
2035  // end extern "C"
2036  fprintf(file, "}/* end extern C */\n");
2037 
2038  fclose(file);
2039  return true;
2040 }
2041 
2042 bool Module::writeHostStub(const char *fn) {
2043  FILE *file = fopen(fn, "w");
2044  if (!file) {
2045  perror("fopen");
2046  return false;
2047  }
2048  fprintf(file, "//\n// %s\n// (device stubs automatically generated by the ispc compiler.)\n", fn);
2049  fprintf(file, "// DO NOT EDIT THIS FILE.\n//\n\n");
2050  fprintf(file, "#include \"ispc/host/offload.h\"\n\n");
2051  fprintf(
2052  file,
2053  "// note(iw): Host stubs do not get extern C linkage -- dev-side already uses that for the same symbols.\n\n");
2054  // fprintf(file,"#ifdef __cplusplus\nextern \"C\" {\n#endif // __cplusplus\n");
2055 
2056  fprintf(file, "#ifdef __cplusplus\nnamespace ispc {\n#endif // __cplusplus\n\n");
2057 
2058  // Collect single linear arrays of the *exported* functions (we'll
2059  // treat those as "__kernel"s in IVL -- "extern" functions will only
2060  // be used for dev-dev function calls; only "export" functions will
2061  // get exported to the host
2062  std::vector<Symbol *> exportedFuncs;
2063  m->symbolTable->GetMatchingFunctions(lIsExported, &exportedFuncs);
2064 
2065  // Get all of the struct, vector, and enumerant types used as function
2066  // parameters. These vectors may have repeats.
2067  std::vector<const StructType *> exportedStructTypes;
2068  std::vector<const EnumType *> exportedEnumTypes;
2069  std::vector<const VectorType *> exportedVectorTypes;
2070  lGetExportedParamTypes(exportedFuncs, &exportedStructTypes, &exportedEnumTypes, &exportedVectorTypes);
2071 
2072  // And print them
2073  lEmitVectorTypedefs(exportedVectorTypes, file);
2074  lEmitEnumDecls(exportedEnumTypes, file);
2075  lEmitStructDecls(exportedStructTypes, file);
2076 
2077  fprintf(file, "\n");
2078  fprintf(file, "///////////////////////////////////////////////////////////////////////////\n");
2079  fprintf(file, "// host-side stubs for dev-side ISPC fucntion(s)\n");
2080  fprintf(file, "///////////////////////////////////////////////////////////////////////////\n");
2081  for (unsigned int i = 0; i < exportedFuncs.size(); ++i) {
2082  const Symbol *sym = exportedFuncs[i];
2083  Assert(sym);
2084  const FunctionType *fct = CastType<FunctionType>(sym->type);
2085  Assert(fct);
2086 
2087  if (!fct->GetReturnType()->IsVoidType()) {
2088  Warning(sym->pos,
2089  "When emitting offload-stubs, ignoring \"export\"ed function with non-void return types.\n");
2090  continue;
2091  }
2092 
2093  // -------------------------------------------------------
2094  // first, emit a struct that holds the parameters
2095  // -------------------------------------------------------
2096  std::string paramStructName = std::string("__ispc_dev_stub_") + sym->name;
2097  std::string paramStruct = emitOffloadParamStruct(paramStructName, sym, fct);
2098  fprintf(file, "%s\n", paramStruct.c_str());
2099  // -------------------------------------------------------
2100  // then, emit a fct stub that unpacks the parameters and pointers
2101  // -------------------------------------------------------
2102 
2103  std::string decl = fct->GetCDeclaration(sym->name);
2104  fprintf(file, "extern %s {\n", decl.c_str());
2105  int numPointers = 0;
2106  fprintf(file, " %s __args;\n", paramStructName.c_str());
2107 
2108  // ------------------------------------------------------------------
2109  // write args, and save pointers for later
2110  // ------------------------------------------------------------------
2111  std::stringstream pointerArgs;
2112  for (int i = 0; i < fct->GetNumParameters(); i++) {
2113  const Type *orgParamType = fct->GetParameterType(i);
2114  std::string paramName = fct->GetParameterName(i);
2115  if (orgParamType->IsPointerType() || orgParamType->IsArrayType()) {
2116  /* we're passing pointers separately -- no pointers in that struct... */
2117  if (numPointers)
2118  pointerArgs << ",";
2119  pointerArgs << "(void*)" << paramName;
2120  numPointers++;
2121  continue;
2122  }
2123 
2124  fprintf(file, " __args.%s = %s;\n", paramName.c_str(), paramName.c_str());
2125  }
2126  // ------------------------------------------------------------------
2127  // writer pointer list
2128  // ------------------------------------------------------------------
2129  if (numPointers == 0)
2130  pointerArgs << "NULL";
2131  fprintf(file, " void *ptr_args[] = { %s };\n", pointerArgs.str().c_str());
2132 
2133  // ------------------------------------------------------------------
2134  // ... and call the kernel with those args
2135  // ------------------------------------------------------------------
2136  fprintf(file, " static ispc_kernel_handle_t kernel_handle = NULL;\n");
2137  fprintf(file, " if (!kernel_handle) kernel_handle = ispc_host_get_kernel_handle(\"__ispc_dev_stub_%s\");\n",
2138  sym->name.c_str());
2139  fprintf(file, " assert(kernel_handle);\n");
2140  fprintf(file,
2141  " ispc_host_call_kernel(kernel_handle,\n"
2142  " &__args, sizeof(__args),\n"
2143  " ptr_args,%i);\n",
2144  numPointers);
2145  fprintf(file, "}\n\n");
2146  }
2147 
2148  // end extern "C"
2149  fprintf(file, "#ifdef __cplusplus\n");
2150  fprintf(file, "}/* namespace */\n");
2151  fprintf(file, "#endif // __cplusplus\n");
2152  // fprintf(file, "#ifdef __cplusplus\n");
2153  // fprintf(file, "}/* end extern C */\n");
2154  // fprintf(file, "#endif // __cplusplus\n");
2155 
2156  fclose(file);
2157  return true;
2158 }
2159 
2160 bool Module::writeHeader(const char *fn) {
2161  FILE *f = fopen(fn, "w");
2162  if (!f) {
2163  perror("fopen");
2164  return false;
2165  }
2166  fprintf(f, "//\n// %s\n// (Header automatically generated by the ispc compiler.)\n", fn);
2167  fprintf(f, "// DO NOT EDIT THIS FILE.\n//\n\n");
2168 
2169  // Create a nice guard string from the filename, turning any
2170  // non-number/letter characters into underbars
2171  std::string guard = "ISPC_";
2172  const char *p = fn;
2173  while (*p) {
2174  if (isdigit(*p))
2175  guard += *p;
2176  else if (isalpha(*p))
2177  guard += toupper(*p);
2178  else
2179  guard += "_";
2180  ++p;
2181  }
2182 
2183  if (g->noPragmaOnce)
2184  fprintf(f, "#ifndef %s\n#define %s\n\n", guard.c_str(), guard.c_str());
2185  else
2186  fprintf(f, "#pragma once\n");
2187 
2188  fprintf(f, "#include <stdint.h>\n\n");
2189 
2190  if (g->emitInstrumentation) {
2191  fprintf(f, "#define ISPC_INSTRUMENTATION 1\n");
2192  fprintf(f, "#if defined(__cplusplus) && (! defined(__ISPC_NO_EXTERN_C) || !__ISPC_NO_EXTERN_C )\nextern \"C\" "
2193  "{\n#endif // __cplusplus\n");
2194  fprintf(f, " void ISPCInstrument(const char *fn, const char *note, int line, uint64_t mask);\n");
2195  fprintf(f, "#if defined(__cplusplus) && (! defined(__ISPC_NO_EXTERN_C) || !__ISPC_NO_EXTERN_C )\n} /* end "
2196  "extern C */\n#endif // __cplusplus\n");
2197  }
2198 
2199  // end namespace
2200  fprintf(f, "\n");
2201  fprintf(f, "\n#ifdef __cplusplus\nnamespace ispc { /* namespace */\n#endif // __cplusplus\n");
2202 
2203  // Collect single linear arrays of the exported and extern "C"
2204  // functions
2205  std::vector<Symbol *> exportedFuncs, externCFuncs;
2206  m->symbolTable->GetMatchingFunctions(lIsExported, &exportedFuncs);
2207  m->symbolTable->GetMatchingFunctions(lIsExternC, &externCFuncs);
2208 
2209  // Get all of the struct, vector, and enumerant types used as function
2210  // parameters. These vectors may have repeats.
2211  std::vector<const StructType *> exportedStructTypes;
2212  std::vector<const EnumType *> exportedEnumTypes;
2213  std::vector<const VectorType *> exportedVectorTypes;
2214  lGetExportedParamTypes(exportedFuncs, &exportedStructTypes, &exportedEnumTypes, &exportedVectorTypes);
2215  lGetExportedParamTypes(externCFuncs, &exportedStructTypes, &exportedEnumTypes, &exportedVectorTypes);
2216 
2217  // Go through the explicitly exported types
2218  for (int i = 0; i < (int)exportedTypes.size(); ++i) {
2219  if (const StructType *st = CastType<StructType>(exportedTypes[i].first))
2220  exportedStructTypes.push_back(st->GetAsUniformType());
2221  else if (const EnumType *et = CastType<EnumType>(exportedTypes[i].first))
2222  exportedEnumTypes.push_back(et->GetAsUniformType());
2223  else if (const VectorType *vt = CastType<VectorType>(exportedTypes[i].first))
2224  exportedVectorTypes.push_back(vt->GetAsUniformType());
2225  else
2226  FATAL("Unexpected type in export list");
2227  }
2228 
2229  // And print them
2230  lEmitVectorTypedefs(exportedVectorTypes, f);
2231  lEmitEnumDecls(exportedEnumTypes, f);
2232  lEmitStructDecls(exportedStructTypes, f);
2233 
2234  // emit function declarations for exported stuff...
2235  if (exportedFuncs.size() > 0) {
2236  fprintf(f, "\n");
2237  fprintf(f, "///////////////////////////////////////////////////////////////////////////\n");
2238  fprintf(f, "// Functions exported from ispc code\n");
2239  fprintf(f, "///////////////////////////////////////////////////////////////////////////\n");
2240  lPrintFunctionDeclarations(f, exportedFuncs);
2241  }
2242 #if 0
2243  if (externCFuncs.size() > 0) {
2244  fprintf(f, "\n");
2245  fprintf(f, "///////////////////////////////////////////////////////////////////////////\n");
2246  fprintf(f, "// External C functions used by ispc code\n");
2247  fprintf(f, "///////////////////////////////////////////////////////////////////////////\n");
2248  lPrintFunctionDeclarations(f, externCFuncs);
2249  }
2250 #endif
2251 
2252  // end namespace
2253  fprintf(f, "\n");
2254  fprintf(f, "\n#ifdef __cplusplus\n} /* namespace */\n#endif // __cplusplus\n");
2255 
2256  // end guard
2257  if (g->noPragmaOnce)
2258  fprintf(f, "\n#endif // %s\n", guard.c_str());
2259 
2260  fclose(f);
2261  return true;
2262 }
2263 
2269  bool Emit4;
2270  bool Emit8;
2271  bool Emit16;
2272  FILE *file;
2273  const char *fn;
2274 };
2275 
2277  FILE *f = DHI->file;
2278 
2279  if (DHI->EmitFrontMatter) {
2280  fprintf(f, "//\n// %s\n// (Header automatically generated by the ispc compiler.)\n", DHI->fn);
2281  fprintf(f, "// DO NOT EDIT THIS FILE.\n//\n\n");
2282  }
2283  // Create a nice guard string from the filename, turning any
2284  // non-number/letter characters into underbars
2285  std::string guard = "ISPC_";
2286  const char *p = DHI->fn;
2287  while (*p) {
2288  if (isdigit(*p))
2289  guard += *p;
2290  else if (isalpha(*p))
2291  guard += toupper(*p);
2292  else
2293  guard += "_";
2294  ++p;
2295  }
2296  if (DHI->EmitFrontMatter) {
2297  if (g->noPragmaOnce)
2298  fprintf(f, "#ifndef %s\n#define %s\n\n", guard.c_str(), guard.c_str());
2299  else
2300  fprintf(f, "#pragma once\n");
2301 
2302  fprintf(f, "#include <stdint.h>\n\n");
2303 
2304  if (g->emitInstrumentation) {
2305  fprintf(f, "#define ISPC_INSTRUMENTATION 1\n");
2306  fprintf(f, "#if defined(__cplusplus) && (! defined(__ISPC_NO_EXTERN_C) || !__ISPC_NO_EXTERN_C )\nextern "
2307  "\"C\" {\n#endif // __cplusplus\n");
2308  fprintf(f, " void ISPCInstrument(const char *fn, const char *note, int line, uint64_t mask);\n");
2309  fprintf(f, "#if defined(__cplusplus) && (! defined(__ISPC_NO_EXTERN_C) || !__ISPC_NO_EXTERN_C )\n} /* end "
2310  "extern C */\n#endif // __cplusplus\n");
2311  }
2312 
2313  // end namespace
2314  fprintf(f, "\n");
2315  fprintf(f, "\n#ifdef __cplusplus\nnamespace ispc { /* namespace */\n#endif // __cplusplus\n\n");
2316  DHI->EmitFrontMatter = false;
2317  }
2318 
2319  // Collect single linear arrays of the exported and extern "C"
2320  // functions
2321  std::vector<Symbol *> exportedFuncs, externCFuncs;
2322  m->symbolTable->GetMatchingFunctions(lIsExported, &exportedFuncs);
2323  m->symbolTable->GetMatchingFunctions(lIsExternC, &externCFuncs);
2324 
2325  int programCount = g->target->getVectorWidth();
2326 
2327  if ((DHI->Emit4 && (programCount == 4)) || (DHI->Emit8 && (programCount == 8)) ||
2328  (DHI->Emit16 && (programCount == 16))) {
2329  // Get all of the struct, vector, and enumerant types used as function
2330  // parameters. These vectors may have repeats.
2331  std::vector<const StructType *> exportedStructTypes;
2332  std::vector<const EnumType *> exportedEnumTypes;
2333  std::vector<const VectorType *> exportedVectorTypes;
2334  lGetExportedParamTypes(exportedFuncs, &exportedStructTypes, &exportedEnumTypes, &exportedVectorTypes);
2335  lGetExportedParamTypes(externCFuncs, &exportedStructTypes, &exportedEnumTypes, &exportedVectorTypes);
2336 
2337  // Go through the explicitly exported types
2338  for (int i = 0; i < (int)exportedTypes.size(); ++i) {
2339  if (const StructType *st = CastType<StructType>(exportedTypes[i].first))
2340  exportedStructTypes.push_back(st->GetAsUniformType());
2341  else if (const EnumType *et = CastType<EnumType>(exportedTypes[i].first))
2342  exportedEnumTypes.push_back(et->GetAsUniformType());
2343  else if (const VectorType *vt = CastType<VectorType>(exportedTypes[i].first))
2344  exportedVectorTypes.push_back(vt->GetAsUniformType());
2345  else
2346  FATAL("Unexpected type in export list");
2347  }
2348 
2349  // And print them
2350  if (DHI->EmitUnifs) {
2351  lEmitVectorTypedefs(exportedVectorTypes, f);
2352  lEmitEnumDecls(exportedEnumTypes, f);
2353  }
2354  lEmitStructDecls(exportedStructTypes, f, DHI->EmitUnifs);
2355 
2356  // Update flags
2357  DHI->EmitUnifs = false;
2358  if (programCount == 4) {
2359  DHI->Emit4 = false;
2360  } else if (programCount == 8) {
2361  DHI->Emit8 = false;
2362  } else if (programCount == 16) {
2363  DHI->Emit16 = false;
2364  }
2365  }
2366  if (DHI->EmitFuncs) {
2367  // emit function declarations for exported stuff...
2368  if (exportedFuncs.size() > 0) {
2369  fprintf(f, "\n");
2370  fprintf(f, "///////////////////////////////////////////////////////////////////////////\n");
2371  fprintf(f, "// Functions exported from ispc code\n");
2372  fprintf(f, "///////////////////////////////////////////////////////////////////////////\n");
2373  lPrintFunctionDeclarations(f, exportedFuncs, 1, true);
2374  fprintf(f, "\n");
2375  }
2376  DHI->EmitFuncs = false;
2377  }
2378 
2379  if (DHI->EmitBackMatter) {
2380  // end namespace
2381  fprintf(f, "\n");
2382  fprintf(f, "\n#ifdef __cplusplus\n} /* namespace */\n#endif // __cplusplus\n");
2383 
2384  // end guard
2385  if (g->noPragmaOnce)
2386  fprintf(f, "\n#endif // %s\n", guard.c_str());
2387  DHI->EmitBackMatter = false;
2388  }
2389 
2390  return true;
2391 }
2392 
2393 void Module::execPreprocessor(const char *infilename, llvm::raw_string_ostream *ostream) const {
2394  clang::CompilerInstance inst;
2395 
2396  llvm::raw_fd_ostream stderrRaw(2, false);
2397 
2398  clang::DiagnosticOptions *diagOptions = new clang::DiagnosticOptions();
2399  clang::TextDiagnosticPrinter *diagPrinter = new clang::TextDiagnosticPrinter(stderrRaw, diagOptions);
2400 
2401  llvm::IntrusiveRefCntPtr<clang::DiagnosticIDs> diagIDs(new clang::DiagnosticIDs);
2402  clang::DiagnosticsEngine *diagEngine = new clang::DiagnosticsEngine(diagIDs, diagOptions, diagPrinter);
2403 
2404  inst.setDiagnostics(diagEngine);
2405 
2406  inst.createFileManager();
2407 
2408 #if ISPC_LLVM_VERSION <= ISPC_LLVM_3_4 // 3.2, 3.3, 3.4
2409  clang::TargetOptions &options = inst.getTargetOpts();
2410 #else // LLVM 3.5+
2411  const std::shared_ptr<clang::TargetOptions> &options = std::make_shared<clang::TargetOptions>(inst.getTargetOpts());
2412 #endif
2413 
2414  llvm::Triple triple(module->getTargetTriple());
2415  if (triple.getTriple().empty()) {
2416  triple.setTriple(llvm::sys::getDefaultTargetTriple());
2417  }
2418 
2419 #if ISPC_LLVM_VERSION <= ISPC_LLVM_3_4 // 3.2, 3.3, 3.4
2420  options.Triple = triple.getTriple();
2421 #else // LLVM 3.5+
2422  options->Triple = triple.getTriple();
2423 #endif
2424 
2425 #if ISPC_LLVM_VERSION == ISPC_LLVM_3_2 // 3.2
2426  clang::TargetInfo *target = clang::TargetInfo::CreateTargetInfo(inst.getDiagnostics(), options);
2427 #elif ISPC_LLVM_VERSION <= ISPC_LLVM_3_4 // 3.3, 3.4
2428  clang::TargetInfo *target = clang::TargetInfo::CreateTargetInfo(inst.getDiagnostics(), &options);
2429 #else // LLVM 3.5+
2430  clang::TargetInfo *target = clang::TargetInfo::CreateTargetInfo(inst.getDiagnostics(), options);
2431 #endif
2432 
2433  inst.setTarget(target);
2434  inst.createSourceManager(inst.getFileManager());
2435 #if ISPC_LLVM_VERSION < ISPC_LLVM_5_0
2436  clang::FrontendInputFile inputFile(infilename, clang::IK_None);
2437 #else // LLVM 5.0+
2438  clang::FrontendInputFile inputFile(infilename, clang::InputKind::Unknown);
2439 #endif
2440  inst.InitializeSourceManager(inputFile);
2441 
2442  // Don't remove comments in the preprocessor, so that we can accurately
2443  // track the source file position by handling them ourselves.
2444  inst.getPreprocessorOutputOpts().ShowComments = 1;
2445 
2446 #if ISPC_LLVM_VERSION >= ISPC_LLVM_3_3 // LLVM 3.3+
2447  inst.getPreprocessorOutputOpts().ShowCPP = 1;
2448 #endif
2449 
2450  clang::HeaderSearchOptions &headerOpts = inst.getHeaderSearchOpts();
2451  headerOpts.UseBuiltinIncludes = 0;
2452  headerOpts.UseStandardSystemIncludes = 0;
2453  headerOpts.UseStandardCXXIncludes = 0;
2454 #ifndef ISPC_NO_DUMPS
2455  if (g->debugPrint)
2456  headerOpts.Verbose = 1;
2457 #endif
2458  for (int i = 0; i < (int)g->includePath.size(); ++i) {
2459  headerOpts.AddPath(g->includePath[i], clang::frontend::Angled,
2460 #if ISPC_LLVM_VERSION == ISPC_LLVM_3_2
2461  true /* is user supplied */,
2462 #endif
2463  false /* not a framework */, true /* ignore sys root */);
2464  }
2465 
2466  clang::PreprocessorOptions &opts = inst.getPreprocessorOpts();
2467 
2468  // Add defs for ISPC and PI
2469  opts.addMacroDef("ISPC");
2470  opts.addMacroDef("PI=3.1415926535");
2471 
2472  // Add #define for current compilation target
2473  char targetMacro[128];
2474  snprintf(targetMacro, sizeof(targetMacro), "ISPC_TARGET_%s", g->target->GetISAString());
2475  char *p = targetMacro;
2476  while (*p) {
2477  *p = toupper(*p);
2478  if (*p == '-')
2479  *p = '_';
2480  ++p;
2481  }
2482  opts.addMacroDef(targetMacro);
2483 
2484  if (g->target->is32Bit())
2485  opts.addMacroDef("ISPC_POINTER_SIZE=32");
2486  else
2487  opts.addMacroDef("ISPC_POINTER_SIZE=64");
2488 
2489  if (g->target->hasHalf())
2490  opts.addMacroDef("ISPC_TARGET_HAS_HALF");
2491  if (g->target->hasRand())
2492  opts.addMacroDef("ISPC_TARGET_HAS_RAND");
2493  if (g->target->hasTranscendentals())
2494  opts.addMacroDef("ISPC_TARGET_HAS_TRANSCENDENTALS");
2495  if (g->opt.forceAlignedMemory)
2496  opts.addMacroDef("ISPC_FORCE_ALIGNED_MEMORY");
2497 
2498  opts.addMacroDef("ISPC_MAJOR_VERSION=1");
2499  opts.addMacroDef("ISPC_MINOR_VERSION=4");
2500 
2501  if (g->includeStdlib) {
2502  if (g->opt.disableAsserts)
2503  opts.addMacroDef("assert(x)=");
2504  else
2505  opts.addMacroDef("assert(x)=__assert(#x, x)");
2506  }
2507 
2508  for (unsigned int i = 0; i < g->cppArgs.size(); ++i) {
2509  // Sanity check--should really begin with -D
2510  if (g->cppArgs[i].substr(0, 2) == "-D") {
2511  opts.addMacroDef(g->cppArgs[i].substr(2));
2512  }
2513  }
2514 #ifdef ISPC_NVPTX_ENABLED
2515  if (g->target->getISA() == Target::NVPTX) {
2516  opts.addMacroDef("__NVPTX__");
2517  opts.addMacroDef("programIndex=__programIndex()");
2518 #if 1
2519  opts.addMacroDef("cif=if");
2520  opts.addMacroDef("cfor=for");
2521  opts.addMacroDef("cwhile=while");
2522  opts.addMacroDef("ccontinue=continue");
2523  opts.addMacroDef("cdo=do");
2524 #endif
2525  opts.addMacroDef("taskIndex0=__taskIndex0()");
2526  opts.addMacroDef("taskIndex1=__taskIndex1()");
2527  opts.addMacroDef("taskIndex2=__taskIndex2()");
2528  opts.addMacroDef("taskIndex=__taskIndex()");
2529  opts.addMacroDef("taskCount0=__taskCount0()");
2530  opts.addMacroDef("taskCount1=__taskCount1()");
2531  opts.addMacroDef("taskCount2=__taskCount2()");
2532  opts.addMacroDef("taskCount=__taskCount()");
2533  }
2534 #endif /* ISPC_NVPTX_ENABLED */
2535 
2536  inst.getLangOpts().LineComment = 1;
2537 
2538 #if ISPC_LLVM_VERSION >= ISPC_LLVM_3_5 /* 3.5+ */
2539  inst.createPreprocessor(clang::TU_Complete);
2540 #else
2541  inst.createPreprocessor();
2542 #endif
2543 
2544  diagPrinter->BeginSourceFile(inst.getLangOpts(), &inst.getPreprocessor());
2545  clang::DoPrintPreprocessedInput(inst.getPreprocessor(), ostream, inst.getPreprocessorOutputOpts());
2546  diagPrinter->EndSourceFile();
2547 }
2548 
2549 // Given an output filename of the form "foo.obj", and an ISA name like
2550 // "avx", return a string with the ISA name inserted before the original
2551 // filename's suffix, like "foo_avx.obj".
2552 static std::string lGetTargetFileName(const char *outFileName, const char *isaString, bool forceCXX) {
2553  int bufferSize = strlen(outFileName) + 16;
2554  char *targetOutFileName = new char[bufferSize];
2555  if (strrchr(outFileName, '.') != NULL) {
2556  // Copy everything up to the last '.'
2557  int count = strrchr(outFileName, '.') - outFileName;
2558  strncpy(targetOutFileName, outFileName, count);
2559  targetOutFileName[count] = '\0';
2560 
2561  // Add the ISA name
2562  strncat(targetOutFileName, "_", bufferSize - strlen(targetOutFileName) - 1);
2563  strncat(targetOutFileName, isaString, bufferSize - strlen(targetOutFileName) - 1);
2564 
2565  // And finish with the original file suffix if it is not *-generic target
2566  if (!forceCXX)
2567  strncat(targetOutFileName, strrchr(outFileName, '.'), bufferSize - strlen(targetOutFileName) - 1);
2568  else
2569  strncat(targetOutFileName, ".cpp", bufferSize - strlen(targetOutFileName) - 1);
2570  } else {
2571  // Can't find a '.' in the filename, so just append the ISA suffix
2572  // to what we weregiven
2573  strncpy(targetOutFileName, outFileName, bufferSize - 1);
2574  targetOutFileName[bufferSize - 1] = '\0';
2575  strncat(targetOutFileName, "_", bufferSize - strlen(targetOutFileName) - 1);
2576  strncat(targetOutFileName, isaString, bufferSize - strlen(targetOutFileName) - 1);
2577 
2578  // Append ".cpp" suffix to the original file if it is *-generic target
2579  if (forceCXX)
2580  strncat(targetOutFileName, ".cpp", bufferSize - strlen(targetOutFileName) - 1);
2581  }
2582  return targetOutFileName;
2583 }
2584 
2585 // Given a comma-delimited string with one or more compilation targets of
2586 // the form "sse2,avx-x2", return a vector of strings where each returned
2587 // string holds one of the targets from the given string.
2588 static std::vector<std::string> lExtractTargets(const char *target) {
2589  std::vector<std::string> targets;
2590  const char *tstart = target;
2591  bool done = false;
2592  while (!done) {
2593  const char *tend = strchr(tstart, ',');
2594  if (tend == NULL) {
2595  done = true;
2596  tend = strchr(tstart, '\0');
2597  }
2598  targets.push_back(std::string(tstart, tend));
2599  tstart = tend + 1;
2600  }
2601  return targets;
2602 }
2603 
2604 static bool lSymbolIsExported(const Symbol *s) { return s->exportedFunction != NULL; }
2605 
2606 // Small structure to hold pointers to the various different versions of a
2607 // llvm::Function that were compiled for different compilation target ISAs.
2610  for (int i = 0; i < Target::NUM_ISAS; ++i) {
2611  func[i] = NULL;
2612  FTs[i] = NULL;
2613  }
2614  }
2615  // The func array is indexed with the Target::ISA enumerant. Some
2616  // values may be NULL, indicating that the original function wasn't
2617  // compiled to the corresponding target ISA.
2618  llvm::Function *func[Target::NUM_ISAS];
2620 };
2621 
2622 // Given the symbol table for a module, return a map from function names to
2623 // FunctionTargetVariants for each function that was defined with the
2624 // 'export' qualifier in ispc.
2625 static void lGetExportedFunctions(SymbolTable *symbolTable, std::map<std::string, FunctionTargetVariants> &functions) {
2626  std::vector<Symbol *> syms;
2628  for (unsigned int i = 0; i < syms.size(); ++i) {
2629  FunctionTargetVariants &ftv = functions[syms[i]->name];
2630  ftv.func[g->target->getISA()] = syms[i]->exportedFunction;
2631  ftv.FTs[g->target->getISA()] = CastType<FunctionType>(syms[i]->type);
2632  }
2633 }
2634 
2635 static llvm::FunctionType *lGetVaryingDispatchType(FunctionTargetVariants &funcs) {
2636  llvm::Type *ptrToInt8Ty = llvm::Type::getInt8PtrTy(*g->ctx);
2637  llvm::FunctionType *resultFuncTy = NULL;
2638 
2639  for (int i = 0; i < Target::NUM_ISAS; ++i) {
2640  if (funcs.func[i] == NULL) {
2641  continue;
2642  } else {
2643  bool foundVarying = false;
2644  const FunctionType *ft = funcs.FTs[i];
2645  resultFuncTy = funcs.func[i]->getFunctionType();
2646 
2647  int numArgs = ft->GetNumParameters();
2648  llvm::SmallVector<llvm::Type *, 8> ftype;
2649  for (int j = 0; j < numArgs; ++j) {
2650  ftype.push_back(resultFuncTy->getParamType(j));
2651  }
2652 
2653  for (int j = 0; j < numArgs; ++j) {
2654  const Type *arg = ft->GetParameterType(j);
2655 
2656  if (arg->IsPointerType()) {
2657  const Type *baseType = CastType<PointerType>(arg)->GetBaseType();
2658  // For each varying type pointed to, swap the LLVM pointer type
2659  // with i8 * (as close as we can get to void *)
2660  if (baseType->IsVaryingType()) {
2661  ftype[j] = ptrToInt8Ty;
2662  foundVarying = true;
2663  }
2664  }
2665  }
2666  if (foundVarying) {
2667  resultFuncTy = llvm::FunctionType::get(resultFuncTy->getReturnType(), ftype, false);
2668  }
2669  }
2670  }
2671 
2672  // We should've found at least one variant here
2673  // or else something fishy is going on.
2674  Assert(resultFuncTy);
2675 
2676  return resultFuncTy;
2677 }
2678 
2679 /** Create the dispatch function for an exported ispc function.
2680  This function checks to see which vector ISAs the system the
2681  code is running on supports and calls out to the best available
2682  variant that was generated at compile time.
2683 
2684  @param module Module in which to create the dispatch function.
2685  @param setISAFunc Pointer to the __set_system_isa() function defined
2686  in builtins-dispatch.ll (which is linked into the
2687  given module before we get here.)
2688  @param systemBestISAPtr Pointer to the module-local __system_best_isa
2689  variable, which holds a value of the Target::ISA
2690  enumerant giving the most capable ISA that the
2691  system supports.
2692  @param name Name of the function for which we're generating a
2693  dispatch function
2694  @param funcs Target-specific variants of the exported function.
2695 */
2696 static void lCreateDispatchFunction(llvm::Module *module, llvm::Function *setISAFunc, llvm::Value *systemBestISAPtr,
2697  const std::string &name, FunctionTargetVariants &funcs) {
2698  // The llvm::Function pointers in funcs are pointers to functions in
2699  // different llvm::Modules, so we can't call them directly. Therefore,
2700  // we'll start by generating an 'extern' declaration of each one that
2701  // we have in the current module so that we can then call out to that.
2702  llvm::Function *targetFuncs[Target::NUM_ISAS];
2703 
2704  // New helper function checks to see if we need to rewrite the
2705  // type for the dispatch function in case of pointers to varyings
2706  llvm::FunctionType *ftype = lGetVaryingDispatchType(funcs);
2707 
2708  // Now we insert type-punned declarations for dispatched functions.
2709  // This is needed when compiling modules for a set of architectures
2710  // with different vector lengths. Due to restrictions, the return
2711  // type is the same across all architectures, however in different
2712  // modules it may have dissimilar names. The loop below works this
2713  // around.
2714  for (int i = 0; i < Target::NUM_ISAS; ++i) {
2715  if (funcs.func[i])
2716  targetFuncs[i] =
2717  llvm::Function::Create(ftype, llvm::GlobalValue::ExternalLinkage, funcs.func[i]->getName(), module);
2718  else
2719  targetFuncs[i] = NULL;
2720  }
2721 
2722  bool voidReturn = ftype->getReturnType()->isVoidTy();
2723 
2724  // Now we can emit the definition of the dispatch function..
2725  llvm::Function *dispatchFunc =
2726  llvm::Function::Create(ftype, llvm::GlobalValue::ExternalLinkage, name.c_str(), module);
2727  llvm::BasicBlock *bblock = llvm::BasicBlock::Create(*g->ctx, "entry", dispatchFunc);
2728 
2729  // Start by calling out to the function that determines the system's
2730  // ISA and sets __system_best_isa, if it hasn't been set yet.
2731  llvm::CallInst::Create(setISAFunc, "", bblock);
2732 
2733  // Now we can load the system's ISA enumerant
2734  llvm::Value *systemISA = new llvm::LoadInst(systemBestISAPtr, "system_isa", bblock);
2735 
2736  // Now emit code that works backwards though the available variants of
2737  // the function. We'll call out to the first one we find that will run
2738  // successfully on the system the code is running on. In working
2739  // through the candidate ISAs here backward, we're taking advantage of
2740  // the expectation that they are ordered in the Target::ISA enumerant
2741  // from least to most capable.
2742  for (int i = Target::NUM_ISAS - 1; i >= 0; --i) {
2743  if (targetFuncs[i] == NULL)
2744  continue;
2745 
2746  // Emit code to see if the system can run the current candidate
2747  // variant successfully--"is the system's ISA enumerant value >=
2748  // the enumerant value of the current candidate?"
2749 
2750  // dispatchNum is needed to separate generic from *-generic target
2751  int dispatchNum = i;
2752  if ((Target::ISA)(i == Target::GENERIC) && !g->target->getTreatGenericAsSmth().empty()) {
2753  if (g->target->getTreatGenericAsSmth() == "knl_generic")
2754  dispatchNum = Target::KNL_AVX512;
2755  else {
2756  Error(SourcePos(), "*-generic target can be called only with knl");
2757  exit(1);
2758  }
2759  }
2760 
2761  llvm::Value *ok = llvm::CmpInst::Create(llvm::Instruction::ICmp, llvm::CmpInst::ICMP_SGE, systemISA,
2762  LLVMInt32(dispatchNum), "isa_ok", bblock);
2763  llvm::BasicBlock *callBBlock = llvm::BasicBlock::Create(*g->ctx, "do_call", dispatchFunc);
2764  llvm::BasicBlock *nextBBlock = llvm::BasicBlock::Create(*g->ctx, "next_try", dispatchFunc);
2765  llvm::BranchInst::Create(callBBlock, nextBBlock, ok, bblock);
2766 
2767  // Emit the code to make the call call in callBBlock.
2768  // Just pass through all of the args from the dispatch function to
2769  // the target-specific function.
2770  std::vector<llvm::Value *> args;
2771  llvm::Function::arg_iterator argIter = dispatchFunc->arg_begin();
2772  llvm::Function::arg_iterator targsIter = targetFuncs[i]->arg_begin();
2773  for (; argIter != dispatchFunc->arg_end(); ++argIter, ++targsIter) {
2774  // Check to see if we rewrote any types in the dispatch function.
2775  // If so, create bitcasts for the appropriate pointer types.
2776  if (argIter->getType() == targsIter->getType()) {
2777  args.push_back(&*argIter);
2778  } else {
2779  llvm::CastInst *argCast = llvm::CastInst::CreatePointerCast(&*argIter, targsIter->getType(),
2780  "dpatch_arg_bitcast", callBBlock);
2781  args.push_back(argCast);
2782  }
2783  }
2784  if (voidReturn) {
2785  llvm::CallInst::Create(targetFuncs[i], args, "", callBBlock);
2786  llvm::ReturnInst::Create(*g->ctx, callBBlock);
2787  } else {
2788  llvm::Value *retValue = llvm::CallInst::Create(targetFuncs[i], args, "ret_value", callBBlock);
2789  llvm::ReturnInst::Create(*g->ctx, retValue, callBBlock);
2790  }
2791 
2792  // Otherwise we'll go on to the next candidate and see about that
2793  // one...
2794  bblock = nextBBlock;
2795  }
2796 
2797  // We couldn't find a match that the current system was capable of
2798  // running. We'll call abort(); this is a bit of a blunt hammer--it
2799  // might be preferable to call a user-supplied callback--ISPCError(...)
2800  // or some such, but we don't want to start imposing too much of a
2801  // runtime library requirement either...
2802  llvm::Function *abortFunc = module->getFunction("abort");
2803  Assert(abortFunc);
2804  llvm::CallInst::Create(abortFunc, "", bblock);
2805 
2806  // Return an undef value from the function here; we won't get to this
2807  // point at runtime, but LLVM needs all of the basic blocks to be
2808  // terminated...
2809  if (voidReturn)
2810  llvm::ReturnInst::Create(*g->ctx, bblock);
2811  else {
2812  llvm::Value *undefRet = llvm::UndefValue::get(ftype->getReturnType());
2813  llvm::ReturnInst::Create(*g->ctx, undefRet, bblock);
2814  }
2815 }
2816 
2817 // Initialize a dispatch module
2818 static llvm::Module *lInitDispatchModule() {
2819  llvm::Module *module = new llvm::Module("dispatch_module", *g->ctx);
2820 
2821  module->setTargetTriple(g->target->GetTripleString());
2822 
2823  // DataLayout information supposed to be managed in single place in Target class.
2824  module->setDataLayout(g->target->getDataLayout()->getStringRepresentation());
2825 
2826  // First, link in the definitions from the builtins-dispatch.ll file.
2827  extern unsigned char builtins_bitcode_dispatch[];
2828  extern int builtins_bitcode_dispatch_length;
2829  AddBitcodeToModule(builtins_bitcode_dispatch, builtins_bitcode_dispatch_length, module);
2830  return module;
2831 }
2832 
2833 // Complete the creation of a dispatch module.
2834 // Given a map that holds the mapping from each of the 'export'ed functions
2835 // in the ispc program to the target-specific variants of the function,
2836 // create a llvm::Module that has a dispatch function for each exported
2837 // function that checks the system's capabilities and picks the most
2838 // appropriate compiled variant of the function.
2839 static void lEmitDispatchModule(llvm::Module *module, std::map<std::string, FunctionTargetVariants> &functions) {
2840  // Get pointers to things we need below
2841  llvm::Function *setFunc = module->getFunction("__set_system_isa");
2842  Assert(setFunc != NULL);
2843  llvm::Value *systemBestISAPtr = module->getGlobalVariable("__system_best_isa", true);
2844  Assert(systemBestISAPtr != NULL);
2845 
2846  // For each exported function, create the dispatch function
2847  std::map<std::string, FunctionTargetVariants>::iterator iter;
2848  for (iter = functions.begin(); iter != functions.end(); ++iter)
2849  lCreateDispatchFunction(module, setFunc, systemBestISAPtr, iter->first, iter->second);
2850 
2851  // Do some rudimentary cleanup of the final result and make sure that
2852  // the module is all ok.
2853 #if ISPC_LLVM_VERSION <= ISPC_LLVM_3_6
2854  llvm::PassManager optPM;
2855 #else // LLVM 3.7+
2856  llvm::legacy::PassManager optPM;
2857 #endif
2858  optPM.add(llvm::createGlobalDCEPass());
2859  optPM.add(llvm::createVerifierPass());
2860  optPM.run(*module);
2861 }
2862 
2863 // Determines if two types are compatible
2864 static bool lCompatibleTypes(llvm::Type *Ty1, llvm::Type *Ty2) {
2865  while (Ty1->getTypeID() == Ty2->getTypeID())
2866  switch (Ty1->getTypeID()) {
2867  case llvm::ArrayType::ArrayTyID:
2868  if (Ty1->getArrayNumElements() != Ty2->getArrayNumElements())
2869  return false;
2870  Ty1 = Ty1->getArrayElementType();
2871  Ty2 = Ty2->getArrayElementType();
2872  break;
2873 
2874  case llvm::ArrayType::PointerTyID:
2875  Ty1 = Ty1->getPointerElementType();
2876  Ty2 = Ty2->getPointerElementType();
2877  break;
2878 
2879  case llvm::ArrayType::StructTyID:
2880  return llvm::dyn_cast<llvm::StructType>(Ty1)->isLayoutIdentical(llvm::dyn_cast<llvm::StructType>(Ty2));
2881 
2882  default:
2883  // Pointers for compatible simple types are assumed equal
2884  return Ty1 == Ty2;
2885  }
2886  return false;
2887 }
2888 
2889 // Grab all of the global value definitions from the module and change them
2890 // to be declarations; we'll emit a single definition of each global in the
2891 // final module used with the dispatch functions, so that we don't have
2892 // multiple definitions of them, one in each of the target-specific output
2893 // files.
2894 static void lExtractOrCheckGlobals(llvm::Module *msrc, llvm::Module *mdst, bool check) {
2895  llvm::Module::global_iterator iter;
2896 
2897  for (iter = msrc->global_begin(); iter != msrc->global_end(); ++iter) {
2898  llvm::GlobalVariable *gv = &*iter;
2899  // Is it a global definition?
2900  if (gv->getLinkage() == llvm::GlobalValue::ExternalLinkage && gv->hasInitializer()) {
2901  // Turn this into an 'extern' declaration by clearing its
2902  // initializer.
2903  llvm::Constant *init = gv->getInitializer();
2904  gv->setInitializer(NULL);
2905 
2906  llvm::Type *type = gv->getType()->getElementType();
2907  Symbol *sym = m->symbolTable->LookupVariable(gv->getName().str().c_str());
2908  Assert(sym != NULL);
2909 
2910  // Check presence and compatibility for the current global
2911  if (check) {
2912  llvm::GlobalVariable *exist = mdst->getGlobalVariable(gv->getName());
2913  Assert(exist != NULL);
2914 
2915  // It is possible that the types may not match: for
2916  // example, this happens with varying globals if we
2917  // compile to different vector widths
2918  if (!lCompatibleTypes(exist->getType(), gv->getType())) {
2919  Warning(sym->pos,
2920  "Mismatch in size/layout of global "
2921  "variable \"%s\" with different targets. "
2922  "Globals must not include \"varying\" types or arrays "
2923  "with size based on programCount when compiling to "
2924  "targets with differing vector widths.",
2925  gv->getName().str().c_str());
2926  }
2927  }
2928  // Alternatively, create it anew and make it match the original
2929  else {
2930  llvm::GlobalVariable *newGlobal = new llvm::GlobalVariable(
2931  *mdst, type, gv->isConstant(), llvm::GlobalValue::ExternalLinkage, init, gv->getName());
2932  newGlobal->copyAttributesFrom(gv);
2933  }
2934  }
2935  }
2936 }
2937 
2938 #ifdef ISPC_NVPTX_ENABLED
2939 static std::string lCBEMangle(const std::string &S) {
2940  std::string Result;
2941 
2942  for (unsigned i = 0, e = S.size(); i != e; ++i) {
2943  if (i + 1 != e && ((S[i] == '>' && S[i + 1] == '>') || (S[i] == '<' && S[i + 1] == '<'))) {
2944  Result += '_';
2945  Result += 'A' + (S[i] & 15);
2946  Result += 'A' + ((S[i] >> 4) & 15);
2947  Result += '_';
2948  i++;
2949  } else if (isalnum(S[i]) || S[i] == '_' || S[i] == '<' || S[i] == '>') {
2950  Result += S[i];
2951  } else {
2952  Result += '_';
2953  Result += 'A' + (S[i] & 15);
2954  Result += 'A' + ((S[i] >> 4) & 15);
2955  Result += '_';
2956  }
2957  }
2958  return Result;
2959 }
2960 #endif /* ISPC_NVPTX_ENABLED */
2961 
2962 int Module::CompileAndOutput(const char *srcFile, const char *arch, const char *cpu, const char *target,
2963  OutputFlags outputFlags, OutputType outputType, const char *outFileName,
2964  const char *headerFileName, const char *includeFileName, const char *depsFileName,
2965  const char *depsTargetName, const char *hostStubFileName, const char *devStubFileName) {
2966  if (target == NULL || strchr(target, ',') == NULL) {
2967  // We're only compiling to a single target
2968  g->target = new Target(arch, cpu, target, 0 != (outputFlags & GeneratePIC), g->printTarget);
2969  if (!g->target->isValid())
2970  return 1;
2971 
2972  m = new Module(srcFile);
2973  if (m->CompileFile() == 0) {
2974 #ifdef ISPC_NVPTX_ENABLED
2975  /* NVPTX:
2976  * for PTX target replace '.' with '_' in all global variables
2977  * a PTX identifier name must match [a-zA-Z$_][a-zA-Z$_0-9]*
2978  */
2979  if (g->target->getISA() == Target::NVPTX) {
2980  /* mangle global variables names */
2981  {
2982  llvm::Module::global_iterator I = m->module->global_begin(), E = m->module->global_end();
2983  for (; I != E; I++)
2984  I->setName(lCBEMangle(I->getName()));
2985  }
2986 
2987  /* mangle functions names */
2988  {
2989  llvm::Module::iterator I = m->module->begin(), E = m->module->end();
2990  for (; I != E; I++) {
2991  std::string str = I->getName();
2992  if (str.find("operator") != std::string::npos)
2993  I->setName(lCBEMangle(str));
2994  }
2995  }
2996  }
2997 #endif /* ISPC_NVPTX_ENABLED */
2998  if (outputType == CXX) {
2999  if (target == NULL || (strncmp(target, "generic-", 8) != 0 && strstr(target, "-generic-") == NULL)) {
3000  Error(SourcePos(), "When generating C++ output, one of the \"generic-*\" "
3001  "targets must be used.");
3002  return 1;
3003  }
3004  } else if (outputType == Asm || outputType == Object) {
3005  if (target != NULL && (strncmp(target, "generic-", 8) == 0 || strstr(target, "-generic-") != NULL)) {
3006  Error(SourcePos(),
3007  "When using a \"generic-*\" compilation target, "
3008  "%s output can not be used.",
3009  (outputType == Asm) ? "assembly" : "object file");
3010  return 1;
3011  }
3012  }
3013 
3014  if (outFileName != NULL)
3015  if (!m->writeOutput(outputType, outputFlags, outFileName, includeFileName))
3016  return 1;
3017  if (headerFileName != NULL)
3018  if (!m->writeOutput(Module::Header, outputFlags, headerFileName))
3019  return 1;
3020  if (depsFileName != NULL || (outputFlags & Module::OutputDepsToStdout)) {
3021  std::string targetName;
3022  if (depsTargetName)
3023  targetName = depsTargetName;
3024  else if (outFileName)
3025  targetName = outFileName;
3026  else if (srcFile) {
3027  targetName = srcFile;
3028  size_t dot = targetName.find_last_of('.');
3029  if (dot != std::string::npos)
3030  targetName.erase(dot, std::string::npos);
3031  targetName.append(".o");
3032  } else
3033  targetName = "a.out";
3034  if (!m->writeOutput(Module::Deps, outputFlags, depsFileName, targetName.c_str(), srcFile))
3035  return 1;
3036  }
3037  if (hostStubFileName != NULL)
3038  if (!m->writeOutput(Module::HostStub, outputFlags, hostStubFileName))
3039  return 1;
3040  if (devStubFileName != NULL)
3041  if (!m->writeOutput(Module::DevStub, outputFlags, devStubFileName))
3042  return 1;
3043  } else
3044  ++m->errorCount;
3045 
3046  int errorCount = m->errorCount;
3047  delete m;
3048  m = NULL;
3049 
3050  delete g->target;
3051  g->target = NULL;
3052 
3053  return errorCount > 0;
3054  } else {
3055  if (outputType == CXX) {
3056  Error(SourcePos(), "Illegal to specify more than one target when "
3057  "compiling C++ output.");
3058  return 1;
3059  }
3060  if (srcFile == NULL || !strcmp(srcFile, "-")) {
3061  Error(SourcePos(), "Compiling programs from standard input isn't "
3062  "supported when compiling for multiple targets. Please use "
3063  "an intermediate temporary file.");
3064  return 1;
3065  }
3066  if (cpu != NULL) {
3067  Error(SourcePos(), "Illegal to specify cpu type when compiling "
3068  "for multiple targets.");
3069  return 1;
3070  }
3071 
3072  // The user supplied multiple targets
3073  std::vector<std::string> targets = lExtractTargets(target);
3074  Assert(targets.size() > 1);
3075 
3076  if (outFileName != NULL && strcmp(outFileName, "-") == 0) {
3077  Error(SourcePos(), "Multi-target compilation can't generate output "
3078  "to stdout. Please provide an output filename.\n");
3079  return 1;
3080  }
3081 
3082  // Make sure that the function names for 'export'ed functions have
3083  // the target ISA appended to them.
3084  g->mangleFunctionsWithTarget = true;
3085 
3086  llvm::TargetMachine *targetMachines[Target::NUM_ISAS];
3087  for (int i = 0; i < Target::NUM_ISAS; ++i)
3088  targetMachines[i] = NULL;
3089 
3090  llvm::Module *dispatchModule = NULL;
3091 
3092  std::map<std::string, FunctionTargetVariants> exportedFunctions;
3093  int errorCount = 0;
3094 
3095  // Handle creating a "generic" header file for multiple targets
3096  // that use exported varyings
3097  DispatchHeaderInfo DHI;
3098  if ((targets.size() > 1) && (headerFileName != NULL)) {
3099  DHI.file = fopen(headerFileName, "w");
3100  if (!DHI.file) {
3101  perror("fopen");
3102  return false;
3103  }
3104  DHI.fn = headerFileName;
3105  DHI.EmitUnifs = true;
3106  DHI.EmitFuncs = true;
3107  DHI.EmitFrontMatter = true;
3108  DHI.Emit4 = true;
3109  DHI.Emit8 = true;
3110  DHI.Emit16 = true;
3111  // This is toggled later.
3112  DHI.EmitBackMatter = false;
3113  }
3114 
3115  // Variable is needed later for approptiate dispatch function.
3116  // It indicates if we have *-generic target.
3117  std::string treatGenericAsSmth = "";
3118 
3119  for (unsigned int i = 0; i < targets.size(); ++i) {
3120  g->target = new Target(arch, cpu, targets[i].c_str(), 0 != (outputFlags & GeneratePIC), g->printTarget);
3121  if (!g->target->isValid())
3122  return 1;
3123 
3124  if (!g->target->getTreatGenericAsSmth().empty())
3125  treatGenericAsSmth = g->target->getTreatGenericAsSmth();
3126 
3127  // Issue an error if we've already compiled to a variant of
3128  // this target ISA. (It doesn't make sense to compile to both
3129  // avx and avx-x2, for example.)
3130  if (targetMachines[g->target->getISA()] != NULL) {
3131  Error(SourcePos(),
3132  "Can't compile to multiple variants of %s "
3133  "target!\n",
3134  g->target->GetISAString());
3135  return 1;
3136  }
3137  targetMachines[g->target->getISA()] = g->target->GetTargetMachine();
3138 
3139  m = new Module(srcFile);
3140  if (m->CompileFile() == 0) {
3141  // Create the dispatch module, unless already created;
3142  // in the latter case, just do the checking
3143  bool check = (dispatchModule != NULL);
3144  if (!check)
3145  dispatchModule = lInitDispatchModule();
3146  lExtractOrCheckGlobals(m->module, dispatchModule, check);
3147 
3148  // Grab pointers to the exported functions from the module we
3149  // just compiled, for use in generating the dispatch function
3150  // later.
3151  lGetExportedFunctions(m->symbolTable, exportedFunctions);
3152 
3153  if (outFileName != NULL) {
3154  std::string targetOutFileName;
3155  // We always generate cpp file for *-generic target during multitarget compilation
3156  if (g->target->getISA() == Target::GENERIC && !g->target->getTreatGenericAsSmth().empty()) {
3157  targetOutFileName =
3158  lGetTargetFileName(outFileName, g->target->getTreatGenericAsSmth().c_str(), true);
3159  if (!m->writeOutput(CXX, outputFlags, targetOutFileName.c_str(), includeFileName))
3160  return 1;
3161  } else {
3162  const char *isaName = g->target->GetISAString();
3163  targetOutFileName = lGetTargetFileName(outFileName, isaName, false);
3164  if (!m->writeOutput(outputType, outputFlags, targetOutFileName.c_str()))
3165  return 1;
3166  }
3167  }
3168  } else {
3169  ++m->errorCount;
3170  }
3171 
3172  errorCount += m->errorCount;
3173  if (errorCount != 0) {
3174  return 1;
3175  }
3176 
3177  // Only write the generate header file, if desired, the first
3178  // time through the loop here.
3179  if (headerFileName != NULL) {
3180  if (i == targets.size() - 1) {
3181  // only print backmatter on the last target.
3182  DHI.EmitBackMatter = true;
3183  }
3184 
3185  const char *isaName;
3186  if (g->target->getISA() == Target::GENERIC && !g->target->getTreatGenericAsSmth().empty())
3187  isaName = g->target->getTreatGenericAsSmth().c_str();
3188  else
3189  isaName = g->target->GetISAString();
3190  std::string targetHeaderFileName = lGetTargetFileName(headerFileName, isaName, false);
3191  // write out a header w/o target name for the first target only
3192  if (!m->writeOutput(Module::Header, outputFlags, headerFileName, "", nullptr, &DHI)) {
3193  return 1;
3194  }
3195  if (!m->writeOutput(Module::Header, outputFlags, targetHeaderFileName.c_str())) {
3196  return 1;
3197  }
3198  if (i == targets.size() - 1) {
3199  fclose(DHI.file);
3200  }
3201  }
3202 
3203  delete g->target;
3204  g->target = NULL;
3205 
3206  // Important: Don't delete the llvm::Module *m here; we need to
3207  // keep it around so the llvm::Functions *s stay valid for when
3208  // we generate the dispatch module's functions...
3209  }
3210 
3211  // Find the first non-NULL target machine from the targets we
3212  // compiled to above. We'll use this as the target machine for
3213  // compiling the dispatch module--this is safe in that it is the
3214  // least-common-denominator of all of the targets we compiled to.
3215  llvm::TargetMachine *firstTargetMachine = NULL;
3216  int i = 0;
3217  const char *firstISA = "";
3218  while (i < Target::NUM_ISAS && firstTargetMachine == NULL) {
3219  firstISA = Target::ISAToTargetString((Target::ISA)i);
3220  firstTargetMachine = targetMachines[i++];
3221  }
3222  Assert(strcmp(firstISA, "") != 0);
3223  Assert(firstTargetMachine != NULL);
3224 
3225  g->target = new Target(arch, cpu, firstISA, 0 != (outputFlags & GeneratePIC), false, treatGenericAsSmth);
3226  if (!g->target->isValid()) {
3227  return 1;
3228  }
3229 
3230  lEmitDispatchModule(dispatchModule, exportedFunctions);
3231 
3232  if (outFileName != NULL) {
3233  if (outputType == Bitcode)
3234  writeBitcode(dispatchModule, outFileName);
3235  else
3236  writeObjectFileOrAssembly(firstTargetMachine, dispatchModule, outputType, outFileName);
3237  }
3238 
3239  if (depsFileName != NULL)
3240  if (!m->writeOutput(Module::Deps, outputFlags, depsFileName))
3241  return 1;
3242 
3243  delete g->target;
3244  g->target = NULL;
3245 
3246  return errorCount > 0;
3247  }
3248 }
int yyparse()
llvm::Value * storagePtr
Definition: sym.h:71
static const AtomicType * VaryingInt32
Definition: type.h:335
bool writeOutput(OutputType ot, OutputFlags flags, const char *filename, const char *includeFileName=NULL, const char *sourceFileName=NULL, DispatchHeaderInfo *DHI=0)
Definition: module.cpp:1155
bool IsReferenceType() const
Definition: type.cpp:205
bool IsUniformType() const
Definition: type.h:139
llvm::Function * function
Definition: sym.h:75
Definition: ast.h:139
Opt opt
Definition: ispc.h:535
void AddTypeDef(const std::string &name, const Type *type, SourcePos pos)
Definition: module.cpp:532
const Type * GetReturnType() const
Definition: type.h:896
virtual const Type * GetAsUnsignedType() const
Definition: type.cpp:2830
std::vector< std::pair< const Type *, SourcePos > > exportedTypes
Definition: module.h:170
bool writeDevStub(const char *filename)
Definition: module.cpp:1907
static void lEmitEnumDecls(const std::vector< const EnumType *> &enumTypes, FILE *file)
Definition: module.cpp:1628
Declaration of the FunctionEmitContext class
bool AddFunction(Symbol *symbol)
Definition: sym.cpp:126
static const AtomicType * VaryingUInt64
Definition: type.h:341
static void lCheckForStructParameters(const FunctionType *ftype, SourcePos pos)
Definition: module.cpp:847
YY_BUFFER_STATE yy_create_buffer(FILE *, int)
bool IsVaryingType() const
Definition: type.h:142
static llvm::Module * lInitDispatchModule()
Definition: module.cpp:2818
static void lCreateDispatchFunction(llvm::Module *module, llvm::Function *setISAFunc, llvm::Value *systemBestISAPtr, const std::string &name, FunctionTargetVariants &funcs)
Definition: module.cpp:2696
bool IsSOAType() const
Definition: type.h:146
#define UNESCAPE_SEQ(c, esc)
std::string getTreatGenericAsSmth() const
Definition: ispc.h:258
static void lExtractOrCheckGlobals(llvm::Module *msrc, llvm::Module *mdst, bool check)
Definition: module.cpp:2894
static bool lSymbolIsExported(const Symbol *s)
Definition: module.cpp:2604
Module * m
Definition: ispc.cpp:102
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
Interface class for statements in the ispc language.
Definition: stmt.h:49
std::string emitOffloadParamStruct(const std::string &paramStructName, const Symbol *sym, const FunctionType *fct)
Definition: module.cpp:1873
int first_line
Definition: ispc.h:133
Structure that defines a compilation target.
Definition: ispc.h:169
int GetSOAWidth() const
Definition: type.h:150
Target * target
Definition: ispc.h:537
void AddBitcodeToModule(const unsigned char *bitcode, int length, llvm::Module *module, SymbolTable *symbolTable=NULL, bool warn=true)
Definition: builtins.cpp:825
bool AddVariable(Symbol *symbol)
Definition: sym.cpp:85
virtual llvm::DIType GetDIType(llvm::DIDescriptor scope) const =0
static void lEmitVectorTypedefs(const std::vector< const VectorType *> &types, FILE *file)
Definition: module.cpp:1666
const std::string & GetParameterName(int i) const
Definition: type.cpp:2817
Expression representing a compile-time constant value.
Definition: expr.h:362
llvm::Function * func[Target::NUM_ISAS]
Definition: module.cpp:2618
Abstract base class for types that represent sequences.
Definition: type.h:512
std::vector< std::string > includePath
Definition: ispc.h:644
std::string GetCDeclaration(const std::string &fname) const
Definition: type.cpp:2598
static void lCheckExportedParameterTypes(const Type *type, const std::string &name, SourcePos pos)
Definition: module.cpp:805
const Type * GetElementType() const
Definition: type.cpp:1303
bool NoOmitFramePointer
Definition: ispc.h:564
std::string Mangle() const
Definition: type.cpp:2584
Symbol table that holds all known symbols during parsing and compilation.
Definition: sym.h:117
std::string GetTripleString() const
Definition: ispc.cpp:1179
void yy_switch_to_buffer(YY_BUFFER_STATE)
Declarations related to optimization passes.
void DefineStdlib(SymbolTable *symbolTable, llvm::LLVMContext *ctx, llvm::Module *module, bool includeStdlib)
Definition: builtins.cpp:1127
static void lGetExportedTypes(const Type *type, std::vector< const StructType *> *exportedStructTypes, std::vector< const EnumType *> *exportedEnumTypes, std::vector< const VectorType *> *exportedVectorTypes)
Definition: module.cpp:1721
bool forceAlignedMemory
Definition: ispc.h:459
const FunctionType * FTs[Target::NUM_ISAS]
Definition: module.cpp:2619
Declarations of functions related to builtins and the standard library.
const char * fn
Definition: module.cpp:2273
bool hasHalf() const
Definition: ispc.h:280
virtual llvm::Constant * GetConstant(const Type *type) const
Definition: expr.cpp:97
int GetNumParameters() const
Definition: type.h:906
std::string name
Definition: sym.h:70
void InitLLVMUtil(llvm::LLVMContext *ctx, Target &target)
Definition: llvmutil.cpp:95
Symbol * LookupVariable(const char *name)
Definition: sym.cpp:112
OutputType
Definition: module.h:91
Type implementation for pointers to other types.
Definition: type.h:430
static bool lIsExternC(const Symbol *sym)
Definition: module.cpp:1805
int TotalElementCount() const
Definition: type.cpp:1382
bool writeHeader(const char *filename)
Definition: module.cpp:2160
const Type * GetBaseType() const
Definition: type.cpp:1488
#define Assert(expr)
Definition: ispc.h:161
ConstExpr * constValue
Definition: sym.h:86
static const StructType * lGetElementStructType(const Type *t)
Definition: module.cpp:1502
bool writeObjectFileOrAssembly(OutputType outputType, const char *filename)
Definition: module.cpp:1407
void GetDirectoryAndFileName(const std::string &currentDir, const std::string &relativeName, std::string *directory, std::string *filename)
Definition: util.cpp:513
virtual llvm::Type * LLVMType(llvm::LLVMContext *ctx) const =0
header file with declarations for symbol and symbol table classes.
bool writeHostStub(const char *filename)
Definition: module.cpp:2042
Type representing a reference to another (non-reference) type.
Definition: type.h:808
static llvm::FunctionType * lGetVaryingDispatchType(FunctionTargetVariants &funcs)
Definition: module.cpp:2635
virtual const Type * GetReferenceTarget() const
Definition: type.cpp:2825
bool includeStdlib
Definition: ispc.h:550
ASTNode * Optimize(ASTNode *root)
Definition: ast.cpp:234
int level
Definition: ispc.h:425
llvm::ConstantInt * LLVMInt32(int32_t i)
Definition: llvmutil.cpp:228
static bool lIsExported(const Symbol *sym)
Definition: module.cpp:1799
llvm::Module * module
Definition: module.h:155
void execPreprocessor(const char *infilename, llvm::raw_string_ostream *ostream) const
Definition: module.cpp:2393
Expr * GetParameterDefault(int i) const
Definition: type.cpp:2807
ASTNode * TypeCheck(ASTNode *root)
Definition: ast.cpp:242
File with declarations for classes related to statements in the language.
struct yy_buffer_state * YY_BUFFER_STATE
Definition: module.cpp:461
llvm::Type * LLVMType(llvm::LLVMContext *ctx) const
Definition: type.cpp:1941
std::set< std::string > registeredDependencies
Definition: module.cpp:139
Globals * g
Definition: ispc.cpp:101
const SourcePos & GetParameterSourcePos(int i) const
Definition: type.cpp:2812
bool debugPrint
Definition: ispc.h:558
static bool writeBitcode(llvm::Module *module, const char *outFileName)
Definition: module.cpp:1339
void RegisterDependency(const std::string &fileName)
Definition: module.cpp:143
static bool lContainsPtrToVarying(const StructType *st)
Definition: module.cpp:1514
const bool isExternC
Definition: type.h:922
void AddExportedTypes(const std::vector< std::pair< const Type *, SourcePos >> &types)
Definition: module.cpp:1142
bool AddType(const char *name, const Type *type, SourcePos pos)
Definition: sym.cpp:165
void Error(SourcePos p, const char *format,...) PRINTF_FUNC
Definition: util.cpp:351
bool LookupFunction(const char *name, std::vector< Symbol *> *matches=NULL)
Definition: sym.cpp:139
void AddFunctionDeclaration(const std::string &name, const FunctionType *ftype, StorageClass sc, bool isInline, SourcePos pos)
Definition: module.cpp:865
bool printTarget
Definition: ispc.h:561
static void lPrintFunctionDeclarations(FILE *file, const std::vector< Symbol *> &funcs, bool useExternC=1, bool rewriteForDispatch=false)
Definition: module.cpp:1775
const Type * GetReferenceTarget() const
Definition: type.cpp:2312
static void lGetExportedParamTypes(const std::vector< Symbol *> &funcs, std::vector< const StructType *> *exportedStructTypes, std::vector< const EnumType *> *exportedEnumTypes, std::vector< const VectorType *> *exportedVectorTypes)
Definition: module.cpp:1760
bool runCPP
Definition: ispc.h:554
static void lDeclareSizeAndPtrIntTypes(SymbolTable *symbolTable)
Definition: module.cpp:148
Representation of a structure holding a number of members.
Definition: type.h:670
int GetValues(bool *, bool forceVarying=false) const
Definition: expr.cpp:5370
char currentDirectory[1024]
Definition: ispc.h:636
bool mangleFunctionsWithTarget
Definition: ispc.h:621
Header file with declarations for various LLVM utility stuff.
const std::string & GetElementName(int i) const
Definition: type.h:719
int CompileFile()
Definition: module.cpp:467
bool emitInstrumentation
Definition: ispc.h:601
SourcePos pos
Definition: sym.h:69
uint32_t RoundUpPow2(uint32_t v)
Definition: util.h:51
Module(const char *filename)
Definition: module.cpp:376
static void lGetExportedFunctions(SymbolTable *symbolTable, std::map< std::string, FunctionTargetVariants > &functions)
Definition: module.cpp:2625
StorageClass storageClass
Definition: sym.h:95
bool hasRand() const
Definition: ispc.h:282
Representation of a range of positions in a source file.
Definition: ispc.h:129
bool generateDebuggingSymbols
Definition: ispc.h:607
Type implementation for enumerated types.
Definition: type.h:355
virtual const Type * GetAsNonConstType() const =0
virtual std::string GetString() const =0
bool hasTranscendentals() const
Definition: ispc.h:288
StorageClass
Definition: ispc.h:120
bool force32BitAddressing
Definition: ispc.h:445
int GetElementCount() const
Definition: type.h:722
bool dllExport
Definition: ispc.h:651
const char * name
Definition: ispc.h:132
void markFuncWithTargetAttr(llvm::Function *func)
Definition: ispc.cpp:1387
static void lEmitStructDecl(const StructType *st, std::vector< const StructType *> *emittedStructs, FILE *file, bool emitUnifs=true)
Definition: module.cpp:1531
SourcePos pos
Definition: ast.h:77
static std::vector< std::string > lExtractTargets(const char *target)
Definition: module.cpp:2588
void Warning(SourcePos p, const char *format,...) PRINTF_FUNC
Definition: util.cpp:375
bool IsVoidType() const
Definition: type.cpp:207
static const AtomicType * VaryingInt64
Definition: type.h:340
int getVectorWidth() const
Definition: ispc.h:272
bool IsPointerType() const
Definition: type.cpp:201
static void lAddTypeIfNew(const Type *type, std::vector< const T *> *exportedTypes)
Definition: module.cpp:1703
#define FATAL(message)
Definition: util.h:112
A (short) vector of atomic types.
Definition: type.h:618
llvm::Type * LLVMType(llvm::LLVMContext *ctx) const
Definition: type.cpp:1545
const Type * GetElementType(const std::string &name) const
Definition: type.cpp:2091
const llvm::DataLayout * getDataLayout() const
Definition: ispc.h:251
static void lEmitStructDecls(std::vector< const StructType *> &structTypes, FILE *file, bool emitUnifs=true)
Definition: module.cpp:1607
const std::string GetCStructName() const
Definition: type.cpp:1762
virtual const Type * GetAsUniformType() const =0
YY_BUFFER_STATE yy_scan_string(const char *)
Representation of a function in a source file.
static void lEmitDispatchModule(llvm::Module *module, std::map< std::string, FunctionTargetVariants > &functions)
Definition: module.cpp:2839
std::string GetCDeclarationForDispatch(const std::string &fname) const
Definition: type.cpp:2626
virtual const Type * GetElementType() const =0
static bool Equal(const Type *a, const Type *b)
Definition: type.cpp:3114
ISA
Definition: ispc.h:177
const bool isTask
Definition: type.h:914
void AddFunctionDefinition(const std::string &name, const FunctionType *ftype, Stmt *code)
Definition: module.cpp:1123
OutputFlags
Definition: module.h:104
ISA getISA() const
Definition: ispc.h:256
const Type * GetParameterType(int i) const
Definition: type.cpp:2802
const char * GetISAString() const
Definition: ispc.cpp:1253
static std::string lGetTargetFileName(const char *outFileName, const char *isaString, bool forceCXX)
Definition: module.cpp:2552
static void lUnescapeStringInPlace(std::string &str)
Definition: module.cpp:1811
Type representing a function (return type + argument types)
Definition: type.h:858
Representation of a program symbol.
Definition: sym.h:63
void AddFunction(Symbol *sym, Stmt *code)
Definition: ast.cpp:55
void GenerateIR()
Definition: ast.cpp:61
virtual bool IsConstType() const =0
Interface class that defines the type abstraction.
Definition: type.h:95
Expr abstract base class and expression implementations.
static const AtomicType * Void
Definition: type.h:343
static bool lRecursiveCheckValidParamType(const Type *t, bool vectorOk)
Definition: module.cpp:765
void GetMatchingFunctions(Predicate pred, std::vector< Symbol *> *matches) const
Definition: sym.h:278
static bool lCompatibleTypes(llvm::Type *Ty1, llvm::Type *Ty2)
Definition: module.cpp:2864
Expr * TypeConvertExpr(Expr *expr, const Type *toType, const char *errorMsgBase)
Definition: expr.cpp:549
int GetElementCount() const
Definition: type.cpp:1301
Expr is the abstract base class that defines the interface that all expression types must implement...
Definition: expr.h:48
static void lStripUnusedDebugInfo(llvm::Module *module)
Definition: module.cpp:168
virtual std::string GetCDeclaration(const std::string &name) const =0
bool noPragmaOnce
Definition: ispc.h:603
bool writeDeps(const char *filename, bool generateMakeRule, const char *targetName=NULL, const char *srcFilename=NULL)
Definition: module.cpp:1842
bool isValid() const
Definition: ispc.h:254
FILE * yyin
static const Type * SizeUnsizedArrays(const Type *type, Expr *initExpr)
Definition: type.cpp:1413
virtual const Type * GetBaseType() const =0
std::vector< std::string > cppArgs
Definition: ispc.h:640
void AddGlobalVariable(const std::string &name, const Type *type, Expr *initExpr, bool isConst, StorageClass storageClass, SourcePos pos)
Definition: module.cpp:538
const bool isExported
Definition: type.h:918
bool is32Bit() const
Definition: ispc.h:262
int GetElementCount() const
Definition: type.cpp:1541
Declaration of the Module class, which is the ispc-side representation of the results of compiling a ...
const VectorType * GetAsNonConstType() const
Definition: type.cpp:1516
int errorCount
Definition: module.h:148
virtual const Type * GetAsUnboundVariabilityType() const =0
llvm::LLVMContext * ctx
Definition: ispc.h:632
llvm::DIFile GetDIFile() const
Definition: ispc.cpp:1487
const char * filename
Definition: module.h:167
void yy_delete_buffer(YY_BUFFER_STATE)
const Type * type
Definition: sym.h:83
llvm::DIBuilder * diBuilder
Definition: module.h:158
static bool EqualIgnoringConst(const Type *a, const Type *b)
Definition: type.cpp:3116
bool disableAsserts
Definition: ispc.h:449
void Debug(SourcePos p, const char *format,...) PRINTF_FUNC
Definition: util.cpp:363
static const AtomicType * VaryingUInt32
Definition: type.h:338
static const char * ISAToTargetString(Target::ISA isa)
Definition: ispc.cpp:1258
const std::string GetReturnTypeString() const
Definition: type.cpp:2714
llvm::TargetMachine * GetTargetMachine() const
Definition: ispc.h:221
SymbolTable * symbolTable
Definition: module.h:152
llvm::Function * exportedFunction
Definition: sym.h:78
bool IsArrayType() const
Definition: type.cpp:203
File with declarations for classes related to type representation.
AST * ast
Definition: module.h:168
llvm::FunctionType * LLVMFunctionType(llvm::LLVMContext *ctx, bool disableMask=false) const
Definition: type.cpp:2738
bool WriteCXXFile(llvm::Module *module, const char *fn, int vectorWidth, const char *includeName)
Definition: cbackend.cpp:5685
bool writeDispatchHeader(DispatchHeaderInfo *DHI)
Definition: module.cpp:2276
One-dimensional array type.
Definition: type.h:535