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