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