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