Intel SPMD Program Compiler  1.10.0
module.cpp
Go to the documentation of this file.
1 /*
2  Copyright (c) 2010-2018, 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, OutputFlags flags, const char *outFileName,
1229  const char *includeFileName, const char *sourceFileName,
1230  DispatchHeaderInfo *DHI) {
1231  if (diBuilder && (outputType != Header) && (outputType != Deps))
1232  lStripUnusedDebugInfo(module);
1233 
1234 #if ISPC_LLVM_VERSION >= ISPC_LLVM_3_4 /* 3.4+ */
1235  // In LLVM_3_4 after r195494 and r195504 revisions we should pass
1236  // "Debug Info Version" constant to the module. LLVM will ignore
1237  // our Debug Info metadata without it.
1238  if (g->generateDebuggingSymbols == true) {
1239  module->addModuleFlag(llvm::Module::Warning, "Debug Info Version", llvm::DEBUG_METADATA_VERSION);
1240  }
1241 #endif
1242 
1243  // SIC! (verifyModule() == TRUE) means "failed", see llvm-link code.
1244  if ((outputType != Header) && (outputType != Deps)
1245  && (outputType != HostStub) && (outputType != DevStub)
1246  && module && llvm::verifyModule(*module))
1247  FATAL("Resulting module verification failed!");
1248 
1249  if (outFileName)
1250  {
1251  // First, issue a warning if the output file suffix and the type of
1252  // file being created seem to mismatch. This can help catch missing
1253  // command-line arguments specifying the output file type.
1254  const char *suffix = strrchr(outFileName, '.');
1255  if (suffix != NULL) {
1256  ++suffix;
1257  const char *fileType = NULL;
1258  switch (outputType) {
1259  case Asm:
1260 #ifdef ISPC_NVPTX_ENABLED
1261  if (g->target->getISA() == Target::NVPTX)
1262  {
1263  if (strcasecmp(suffix, "ptx"))
1264  fileType = "assembly";
1265  }
1266  else
1267 #endif /* ISPC_NVPTX_ENABLED */
1268  if (strcasecmp(suffix, "s"))
1269  fileType = "assembly";
1270  break;
1271  case Bitcode:
1272 #ifdef ISPC_NVPTX_ENABLED
1273  if (g->target->getISA() == Target::NVPTX)
1274  {
1275  if (strcasecmp(suffix, "ll"))
1276  fileType = "LLVM assembly";
1277  }
1278  else
1279 #endif /* ISPC_NVPTX_ENABLED */
1280  if (strcasecmp(suffix, "bc"))
1281  fileType = "LLVM bitcode";
1282  break;
1283  case Object:
1284  if (strcasecmp(suffix, "o") && strcasecmp(suffix, "obj"))
1285  fileType = "object";
1286  break;
1287  case CXX:
1288  if (strcasecmp(suffix, "c") && strcasecmp(suffix, "cc") &&
1289  strcasecmp(suffix, "c++") && strcasecmp(suffix, "cxx") &&
1290  strcasecmp(suffix, "cpp"))
1291  fileType = "c++";
1292  break;
1293  case Header:
1294  if (strcasecmp(suffix, "h") && strcasecmp(suffix, "hh") &&
1295  strcasecmp(suffix, "hpp"))
1296  fileType = "header";
1297  break;
1298  case Deps:
1299  break;
1300  case DevStub:
1301  if (strcasecmp(suffix, "c") && strcasecmp(suffix, "cc") &&
1302  strcasecmp(suffix, "c++") && strcasecmp(suffix, "cxx") &&
1303  strcasecmp(suffix, "cpp"))
1304  fileType = "dev-side offload stub";
1305  break;
1306  case HostStub:
1307  if (strcasecmp(suffix, "c") && strcasecmp(suffix, "cc") &&
1308  strcasecmp(suffix, "c++") && strcasecmp(suffix, "cxx") &&
1309  strcasecmp(suffix, "cpp"))
1310  fileType = "host-side offload stub";
1311  break;
1312  default:
1313  Assert(0 /* swtich case not handled */);
1314  return 1;
1315  }
1316  if (fileType != NULL)
1317  Warning(SourcePos(), "Emitting %s file, but filename \"%s\" "
1318  "has suffix \"%s\"?", fileType, outFileName, suffix);
1319  }
1320  }
1321 
1322  if (outputType == Header) {
1323  if (DHI)
1324  return writeDispatchHeader(DHI);
1325  else
1326  return writeHeader(outFileName);
1327  }
1328  else if (outputType == Deps)
1329  return writeDeps(outFileName, 0 != (flags & GenerateMakeRuleForDeps), includeFileName, sourceFileName);
1330  else if (outputType == HostStub)
1331  return writeHostStub(outFileName);
1332  else if (outputType == DevStub)
1333  return writeDevStub(outFileName);
1334  else if (outputType == Bitcode)
1335  return writeBitcode(module, outFileName);
1336  else if (outputType == CXX) {
1337  if (g->target->getISA() != Target::GENERIC) {
1338  Error(SourcePos(), "Only \"generic-*\" targets can be used with "
1339  "C++ emission.");
1340  return false;
1341  }
1342  extern bool WriteCXXFile(llvm::Module *module, const char *fn,
1343  int vectorWidth, const char *includeName);
1344  return WriteCXXFile(module, outFileName, g->target->getVectorWidth(),
1345  includeFileName);
1346  }
1347  else
1348  return writeObjectFileOrAssembly(outputType, outFileName);
1349 }
1350 
1351 #ifdef ISPC_NVPTX_ENABLED
1352 typedef std::vector<std::string> vecString_t;
1353 static vecString_t
1354 lSplitString(const std::string &s)
1355 {
1356  std::stringstream ss(s);
1357  std::istream_iterator<std::string> begin(ss);
1358  std::istream_iterator<std::string> end;
1359  return vecString_t(begin,end);
1360 }
1361 
1362 static void
1363 lFixAttributes(const vecString_t &src, vecString_t &dst)
1364 {
1365  dst.clear();
1366 
1367  std::vector< std::pair<int,int> > attributePos;
1368 
1369  typedef std::map<std::string, std::string> attributeMap_t;
1370  attributeMap_t attributeMap;
1371 
1372 #ifdef ISPC_NVPTX_NVVM_OLD /* guard for NVVM from CUDA TK < 7.0 */
1373  for (vecString_t::const_iterator it = src.begin(); it != src.end(); it++)
1374  {
1375  const vecString_t words = lSplitString(*it);
1376  if (!words.empty() && words[0] == "attributes" && words[1][0] == '#')
1377  {
1378  const int nWords = words.size();
1379  assert(nWords > 3);
1380  assert(words[2 ] == "=");
1381  assert(words[3 ] == "{");
1382  assert(words[nWords-1] == "}");
1383  std::string attributes;
1384  for (int w = 4; w < nWords-1; w++)
1385  attributes += words[w] + " ";
1386  attributeMap[words[1]] = attributes;
1387  }
1388  }
1389 #endif
1390 
1391  for (vecString_t::const_iterator it = src.begin(); it != src.end(); it++)
1392  {
1393  vecString_t words = lSplitString(*it);
1394  /* evghenii: is there a cleaner way to set target datalayout for ptx ? */
1395  if (words.size() > 1 && (words[0] == "target" && words[1] == "datalayout"))
1396  {
1397  std::string s = "target datalayout = ";
1398  s += '"';
1399  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";
1400  s += '"';
1401  dst.push_back(s);
1402  continue;
1403  }
1404  if (!words.empty() && words[0] == "attributes")
1405  continue;
1406  std::string s;
1407  std::map<std::string, std::string> attributeSet;
1408 #ifdef ISPC_NVPTX_NVVM_OLD /* guard for NVVM from CUDA TK < 7.0 */
1409  /* this attributed cannot be used in function parameters, so remove them */
1410  attributeSet["readnone"] = " ";
1411  attributeSet["readonly"] = " ";
1412  attributeSet["readnone,"] = ",";
1413  attributeSet["readonly,"] = ",";
1414 #endif
1415 
1416 
1417  for (vecString_t::iterator w = words.begin(); w != words.end(); w++)
1418  {
1419  if (attributeSet.find(*w) != attributeSet.end())
1420  *w = attributeSet[*w];
1421 
1422  if ((*w)[0] == '#')
1423  {
1424  attributeMap_t::iterator m = attributeMap.find(*w);
1425  if (m != attributeMap.end())
1426  *w = attributeMap[*w];
1427  }
1428  s += *w + " ";
1429  }
1430  dst.push_back(s);
1431  }
1432 }
1433 #endif /* ISPC_NVPTX_ENABLED */
1434 
1435 bool
1436 Module::writeBitcode(llvm::Module *module, const char *outFileName) {
1437  // Get a file descriptor corresponding to where we want the output to
1438  // go. If we open it, it'll be closed by the llvm::raw_fd_ostream
1439  // destructor.
1440  int fd;
1441  if (!strcmp(outFileName, "-"))
1442  fd = 1; // stdout
1443  else {
1444  int flags = O_CREAT|O_WRONLY|O_TRUNC;
1445 #ifdef ISPC_IS_WINDOWS
1446  flags |= O_BINARY;
1447  fd = _open(outFileName, flags, 0644);
1448 #else
1449  fd = open(outFileName, flags, 0644);
1450 #endif // ISPC_IS_WINDOWS
1451  if (fd == -1) {
1452  perror(outFileName);
1453  return false;
1454  }
1455  }
1456 
1457  llvm::raw_fd_ostream fos(fd, (fd != 1), false);
1458 #ifdef ISPC_NVPTX_ENABLED
1459  if (g->target->getISA() == Target::NVPTX)
1460  {
1461  /* when using "nvptx" target, emit patched/hacked assembly
1462  * NVPTX only accepts 3.2-style LLVM assembly, where attributes
1463  * must be inlined, rather then referenced by #attribute_d
1464  * As soon as NVVM support 3.3,3.4 style assembly this fix won't be needed
1465  */
1466  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";
1467  module->setDataLayout(dl_string);
1468 
1469  std::string s;
1470  llvm::raw_string_ostream out(s);
1471 #if ISPC_LLVM_VERSION >= ISPC_LLVM_3_5 /* 3.5+ */
1472  std::unique_ptr<llvm::AssemblyAnnotationWriter> Annotator;
1473 #else
1474  llvm::OwningPtr<llvm::AssemblyAnnotationWriter> Annotator;
1475 #endif
1476  module->print(out, Annotator.get());
1477  std::istringstream iss(s);
1478 
1479  vecString_t input,output;
1480  while (std::getline(iss,s))
1481  input.push_back(s);
1482  output = input;
1483 
1484 #if ISPC_LLVM_VERSION >= ISPC_LLVM_3_3 /* 3.3+ */
1485  /* do not fix attributed with LLVM 3.2, everything is fine there */
1486  lFixAttributes(input,output);
1487 #endif
1488 
1489  for (vecString_t::iterator it = output.begin(); it != output.end(); it++)
1490  {
1491  *it += "\n";
1492  fos << *it;
1493  }
1494  }
1495  else
1496 #endif /* ISPC_NVPTX_ENABLED */
1497 #if ISPC_LLVM_VERSION < ISPC_LLVM_7_0
1498  llvm::WriteBitcodeToFile(module, fos);
1499 #else
1500  llvm::WriteBitcodeToFile(*module, fos);
1501 #endif
1502 
1503  return true;
1504 }
1505 
1506 
1507 bool
1508 Module::writeObjectFileOrAssembly(OutputType outputType, const char *outFileName) {
1509  llvm::TargetMachine *targetMachine = g->target->GetTargetMachine();
1510  return writeObjectFileOrAssembly(targetMachine, module, outputType,
1511  outFileName);
1512 }
1513 
1514 
1515 bool
1516 Module::writeObjectFileOrAssembly(llvm::TargetMachine *targetMachine,
1517  llvm::Module *module, OutputType outputType,
1518  const char *outFileName) {
1519  // Figure out if we're generating object file or assembly output, and
1520  // set binary output for object files
1521  llvm::TargetMachine::CodeGenFileType fileType = (outputType == Object) ?
1522  llvm::TargetMachine::CGFT_ObjectFile : llvm::TargetMachine::CGFT_AssemblyFile;
1523  bool binary = (fileType == llvm::TargetMachine::CGFT_ObjectFile);
1524 #if ISPC_LLVM_VERSION <= ISPC_LLVM_3_3 // 3.2, 3.3
1525  unsigned int flags = binary ? llvm::raw_fd_ostream::F_Binary : 0;
1526 #elif ISPC_LLVM_VERSION == ISPC_LLVM_3_4 // 3.4
1527  llvm::sys::fs::OpenFlags flags = binary ? llvm::sys::fs::F_Binary :
1528  llvm::sys::fs::F_None;
1529 #else // LLVM 3.5+
1530  llvm::sys::fs::OpenFlags flags = binary ? llvm::sys::fs::F_None :
1531  llvm::sys::fs::F_Text;
1532 
1533 #endif
1534 
1535 #if ISPC_LLVM_VERSION <= ISPC_LLVM_3_5
1536  std::string error;
1537 #else // LLVM 3.6+
1538  std::error_code error;
1539 #endif
1540 
1541 #if ISPC_LLVM_VERSION <= ISPC_LLVM_3_6
1542  llvm::tool_output_file *of = new llvm::tool_output_file(outFileName, error, flags);
1543 #elif ISPC_LLVM_VERSION <= ISPC_LLVM_5_0 // LLVM 3.7-5.0
1544  std::unique_ptr<llvm::tool_output_file> of (new llvm::tool_output_file(outFileName, error, flags));
1545 #else // LLVM 6.0+
1546  std::unique_ptr<llvm::ToolOutputFile> of (new llvm::ToolOutputFile(outFileName, error, flags));
1547 #endif
1548 
1549 #if ISPC_LLVM_VERSION <= ISPC_LLVM_3_5
1550  if (error.size()) {
1551 #else // LLVM 3.6+
1552  if (error) {
1553 #endif
1554 
1555  fprintf(stderr, "Error opening output file \"%s\".\n", outFileName);
1556  return false;
1557  }
1558 
1559 #if ISPC_LLVM_VERSION <= ISPC_LLVM_3_6
1560  llvm::PassManager pm;
1561 #else // LLVM 3.7+
1562  llvm::legacy::PassManager pm;
1563 #endif
1564 #if ISPC_LLVM_VERSION <= ISPC_LLVM_3_4 // 3.2, 3.3, 3.4
1565  pm.add(new llvm::DataLayout(*g->target->getDataLayout()));
1566 #elif ISPC_LLVM_VERSION == ISPC_LLVM_3_5 // 3.5
1567  pm.add(new llvm::DataLayoutPass(*g->target->getDataLayout()));
1568 #elif ISPC_LLVM_VERSION == ISPC_LLVM_3_6 // 3.6
1569  llvm::DataLayoutPass *dlp= new llvm::DataLayoutPass();
1570  dlp->doInitialization(*module);
1571  pm.add(dlp);
1572 #endif // LLVM 3.7+ doesn't have DataLayoutPass anymore.
1573 
1574  {
1575 #if ISPC_LLVM_VERSION <= ISPC_LLVM_3_6
1576  llvm::formatted_raw_ostream fos(of->os());
1577 #else // LLVM 3.7+
1578  llvm::raw_fd_ostream &fos(of->os());
1579 #endif
1580 #if ISPC_LLVM_VERSION <= ISPC_LLVM_6_0
1581  if (targetMachine->addPassesToEmitFile(pm, fos, fileType)) {
1582  fprintf(stderr, "Fatal error adding passes to emit object file!");
1583  exit(1);
1584  }
1585 #else // LLVM 7.0+
1586  // Third parameter is for generation of .dwo file, which is separate DWARF
1587  // file for ELF targets. We don't support it currently.
1588  if (targetMachine->addPassesToEmitFile(pm, fos, nullptr, fileType)) {
1589  fprintf(stderr, "Fatal error adding passes to emit object file!");
1590  exit(1);
1591  }
1592 #endif
1593 
1594  // Finally, run the passes to emit the object file/assembly
1595  pm.run(*module);
1596 
1597  // Success; tell tool_output_file to keep the final output file.
1598  of->keep();
1599  }
1600 #if ISPC_LLVM_VERSION <= ISPC_LLVM_3_6
1601  delete of;
1602 #endif // LLVM 3.7+
1603  return true;
1604 }
1605 
1606 
1607 /** Given a pointer to an element of a structure, see if it is a struct
1608  type or an array of a struct type. If so, return a pointer to the
1609  underlying struct type. */
1610 static const StructType *
1612  const StructType *st = CastType<StructType>(t);
1613  if (st != NULL)
1614  return st;
1615 
1616  const ArrayType *at = CastType<ArrayType>(t);
1617  if (at != NULL)
1618  return lGetElementStructType(at->GetElementType());
1619 
1620  return NULL;
1621 }
1622 
1623 static bool
1625  int numElts = st->GetElementCount();
1626 
1627  for (int j = 0; j < numElts; ++j) {
1628  const Type *t = st->GetElementType(j);
1629 
1630  if (t->IsVaryingType()) return true;
1631  }
1632 
1633  return false;
1634 }
1635 
1636 
1637 /** Emits a declaration for the given struct to the given file. This
1638  function first makes sure that declarations for any structs that are
1639  (recursively) members of this struct are emitted first.
1640  */
1641 static void
1642 lEmitStructDecl(const StructType *st, std::vector<const StructType *> *emittedStructs,
1643  FILE *file, bool emitUnifs=true) {
1644 
1645  // if we're emitting this for a generic dispatch header file and it's
1646  // struct that only contains uniforms, don't bother if we're emitting uniforms
1647  if (!emitUnifs && !lContainsPtrToVarying(st)) {
1648  return;
1649  }
1650 
1651  // Has this struct type already been declared? (This happens if it's a
1652  // member of another struct for which we emitted a declaration
1653  // previously.)
1654  for (int i = 0; i < (int)emittedStructs->size(); ++i)
1655  if (Type::EqualIgnoringConst(st, (*emittedStructs)[i]))
1656  return;
1657 
1658  // Otherwise first make sure any contained structs have been declared.
1659  for (int i = 0; i < st->GetElementCount(); ++i) {
1660  const StructType *elementStructType =
1662  if (elementStructType != NULL)
1663  lEmitStructDecl(elementStructType, emittedStructs, file, emitUnifs);
1664  }
1665 
1666  // And now it's safe to declare this one
1667  emittedStructs->push_back(st);
1668 
1669  fprintf(file, "#ifndef __ISPC_STRUCT_%s__\n",st->GetCStructName().c_str());
1670  fprintf(file, "#define __ISPC_STRUCT_%s__\n",st->GetCStructName().c_str());
1671 
1672  char sSOA[48];
1673  bool pack, needsAlign = false;
1674  llvm::Type *stype = st->LLVMType(g->ctx);
1675  const llvm::DataLayout *DL = g->target->getDataLayout();
1676 
1677  if (!(pack = llvm::dyn_cast<llvm::StructType>(stype)->isPacked()))
1678  for (int i = 0; !needsAlign && (i < st->GetElementCount()); ++i) {
1679  const Type *ftype = st->GetElementType(i)->GetAsNonConstType();
1680  needsAlign |= ftype->IsVaryingType()
1681  && (CastType<StructType>(ftype) == NULL);
1682  }
1683  if (st->GetSOAWidth() > 0)
1684  // This has to match the naming scheme in
1685  // StructType::GetCDeclaration().
1686  sprintf(sSOA, "_SOA%d", st->GetSOAWidth());
1687  else
1688  *sSOA = '\0';
1689  if (!needsAlign)
1690  fprintf(file, "%sstruct %s%s {\n", (pack)? "packed " : "",
1691  st->GetCStructName().c_str(), sSOA);
1692  else {
1693  unsigned uABI = DL->getABITypeAlignment(stype);
1694  fprintf(file, "__ISPC_ALIGNED_STRUCT__(%u) %s%s {\n", uABI,
1695  st->GetCStructName().c_str(), sSOA);
1696  }
1697  for (int i = 0; i < st->GetElementCount(); ++i) {
1698  const Type *ftype = st->GetElementType(i)->GetAsNonConstType();
1699  std::string d = ftype->GetCDeclaration(st->GetElementName(i));
1700 
1701  fprintf(file, " ");
1702  if (needsAlign && ftype->IsVaryingType() &&
1703  (CastType<StructType>(ftype) == NULL)) {
1704  unsigned uABI = DL->getABITypeAlignment(ftype->LLVMType(g->ctx));
1705  fprintf(file, "__ISPC_ALIGN__(%u) ", uABI);
1706  }
1707  // Don't expand arrays, pointers and structures:
1708  // their insides will be expanded automatically.
1709  if (!ftype->IsArrayType() && !ftype->IsPointerType() &&
1710  ftype->IsVaryingType() && (CastType<StructType>(ftype) == NULL)) {
1711  fprintf(file, "%s[%d];\n", d.c_str(), g->target->getVectorWidth());
1712  }
1713  else {
1714  fprintf(file, "%s;\n", d.c_str());
1715  }
1716  }
1717  fprintf(file, "};\n");
1718  fprintf(file, "#endif\n\n");
1719 }
1720 
1721 
1722 /** Given a set of structures that we want to print C declarations of in a
1723  header file, emit their declarations.
1724  */
1725 static void
1726 lEmitStructDecls(std::vector<const StructType *> &structTypes, FILE *file, bool emitUnifs=true) {
1727  std::vector<const StructType *> emittedStructs;
1728 
1729  fprintf(file,
1730  "\n#ifndef __ISPC_ALIGN__\n"
1731  "#if defined(__clang__) || !defined(_MSC_VER)\n"
1732  "// Clang, GCC, ICC\n"
1733  "#define __ISPC_ALIGN__(s) __attribute__((aligned(s)))\n"
1734  "#define __ISPC_ALIGNED_STRUCT__(s) struct __ISPC_ALIGN__(s)\n"
1735  "#else\n"
1736  "// Visual Studio\n"
1737  "#define __ISPC_ALIGN__(s) __declspec(align(s))\n"
1738  "#define __ISPC_ALIGNED_STRUCT__(s) __ISPC_ALIGN__(s) struct\n"
1739  "#endif\n"
1740  "#endif\n\n");
1741 
1742  for (unsigned int i = 0; i < structTypes.size(); ++i)
1743  lEmitStructDecl(structTypes[i], &emittedStructs, file, emitUnifs);
1744 }
1745 
1746 
1747 /** Emit C declarations of enumerator types to the generated header file.
1748  */
1749 static void
1750 lEmitEnumDecls(const std::vector<const EnumType *> &enumTypes, FILE *file) {
1751  if (enumTypes.size() == 0)
1752  return;
1753 
1754  fprintf(file, "///////////////////////////////////////////////////////////////////////////\n");
1755  fprintf(file, "// Enumerator types with external visibility from ispc code\n");
1756  fprintf(file, "///////////////////////////////////////////////////////////////////////////\n\n");
1757 
1758  for (unsigned int i = 0; i < enumTypes.size(); ++i) {
1759  fprintf(file, "#ifndef __ISPC_ENUM_%s__\n",enumTypes[i]->GetEnumName().c_str());
1760  fprintf(file, "#define __ISPC_ENUM_%s__\n",enumTypes[i]->GetEnumName().c_str());
1761  std::string declaration = enumTypes[i]->GetCDeclaration("");
1762  fprintf(file, "%s {\n", declaration.c_str());
1763 
1764  // Print the individual enumerators
1765  for (int j = 0; j < enumTypes[i]->GetEnumeratorCount(); ++j) {
1766  const Symbol *e = enumTypes[i]->GetEnumerator(j);
1767  Assert(e->constValue != NULL);
1768  unsigned int enumValue;
1769  int count = e->constValue->GetValues(&enumValue);
1770  Assert(count == 1);
1771 
1772  // Always print an initializer to set the value. We could be
1773  // 'clever' here and detect whether the implicit value given by
1774  // one plus the previous enumerator value (or zero, for the
1775  // first enumerator) is the same as the value stored with the
1776  // enumerator, though that doesn't seem worth the trouble...
1777  fprintf(file, " %s = %d%c\n", e->name.c_str(), enumValue,
1778  (j < enumTypes[i]->GetEnumeratorCount() - 1) ? ',' : ' ');
1779  }
1780  fprintf(file, "};\n");
1781  fprintf(file, "#endif\n\n");
1782  }
1783 }
1784 
1785 
1786 /** Print declarations of VectorTypes used in 'export'ed parts of the
1787  program in the header file.
1788  */
1789 static void
1790 lEmitVectorTypedefs(const std::vector<const VectorType *> &types, FILE *file) {
1791  if (types.size() == 0)
1792  return;
1793 
1794  fprintf(file, "///////////////////////////////////////////////////////////////////////////\n");
1795  fprintf(file, "// Vector types with external visibility from ispc code\n");
1796  fprintf(file, "///////////////////////////////////////////////////////////////////////////\n\n");
1797 
1798  for (unsigned int i = 0; i < types.size(); ++i) {
1799  std::string baseDecl;
1800  const VectorType *vt = types[i]->GetAsNonConstType();
1801  if (!vt->IsUniformType())
1802  // Varying stuff shouldn't be visibile to / used by the
1803  // application, so at least make it not simple to access it by
1804  // not declaring the type here...
1805  continue;
1806 
1807  int size = vt->GetElementCount();
1808 
1809  llvm::Type *ty = vt->LLVMType(g->ctx);
1810  int align = g->target->getDataLayout()->getABITypeAlignment(ty);
1811  baseDecl = vt->GetBaseType()->GetCDeclaration("");
1812  fprintf(file, "#ifndef __ISPC_VECTOR_%s%d__\n",baseDecl.c_str(), size);
1813  fprintf(file, "#define __ISPC_VECTOR_%s%d__\n",baseDecl.c_str(), size);
1814  fprintf(file, "#ifdef _MSC_VER\n__declspec( align(%d) ) ", align);
1815  fprintf(file, "struct %s%d { %s v[%d]; };\n", baseDecl.c_str(), size,
1816  baseDecl.c_str(), size);
1817  fprintf(file, "#else\n");
1818  fprintf(file, "struct %s%d { %s v[%d]; } __attribute__ ((aligned(%d)));\n",
1819  baseDecl.c_str(), size, baseDecl.c_str(), size, align);
1820  fprintf(file, "#endif\n");
1821  fprintf(file, "#endif\n\n");
1822  }
1823  fprintf(file, "\n");
1824 }
1825 
1826 
1827 /** Add the given type to the vector, if that type isn't already in there.
1828  */
1829 template <typename T> static void
1830 lAddTypeIfNew(const Type *type, std::vector<const T *> *exportedTypes) {
1831  type = type->GetAsNonConstType();
1832 
1833  // Linear search, so this ends up being n^2. It's unlikely this will
1834  // matter in practice, though.
1835  for (unsigned int i = 0; i < exportedTypes->size(); ++i)
1836  if (Type::Equal((*exportedTypes)[i], type))
1837  return;
1838 
1839  const T *castType = CastType<T>(type);
1840  Assert(castType != NULL);
1841  exportedTypes->push_back(castType);
1842 }
1843 
1844 
1845 /** Given an arbitrary type that appears in the app/ispc interface, add it
1846  to an appropriate vector if it is a struct, enum, or short vector type.
1847  Then, if it's a struct, recursively process its members to do the same.
1848  */
1849 static void
1851  std::vector<const StructType *> *exportedStructTypes,
1852  std::vector<const EnumType *> *exportedEnumTypes,
1853  std::vector<const VectorType *> *exportedVectorTypes) {
1854  const ArrayType *arrayType = CastType<ArrayType>(type);
1855  const StructType *structType = CastType<StructType>(type);
1856  const FunctionType *ftype = CastType<FunctionType>(type);
1857 
1858  if (CastType<ReferenceType>(type) != NULL)
1859  lGetExportedTypes(type->GetReferenceTarget(), exportedStructTypes,
1860  exportedEnumTypes, exportedVectorTypes);
1861  else if (CastType<PointerType>(type) != NULL)
1862  lGetExportedTypes(type->GetBaseType(), exportedStructTypes,
1863  exportedEnumTypes, exportedVectorTypes);
1864  else if (arrayType != NULL)
1865  lGetExportedTypes(arrayType->GetElementType(), exportedStructTypes,
1866  exportedEnumTypes, exportedVectorTypes);
1867  else if (structType != NULL) {
1868  lAddTypeIfNew(type, exportedStructTypes);
1869  for (int i = 0; i < structType->GetElementCount(); ++i)
1870  lGetExportedTypes(structType->GetElementType(i), exportedStructTypes,
1871  exportedEnumTypes, exportedVectorTypes);
1872  }
1873  else if (CastType<UndefinedStructType>(type) != NULL)
1874  // do nothing
1875  ;
1876  else if (CastType<EnumType>(type) != NULL)
1877  lAddTypeIfNew(type, exportedEnumTypes);
1878  else if (CastType<VectorType>(type) != NULL)
1879  lAddTypeIfNew(type, exportedVectorTypes);
1880  else if (ftype != NULL) {
1881  // Handle Return Types
1882  lGetExportedTypes(ftype->GetReturnType(), exportedStructTypes,
1883  exportedEnumTypes, exportedVectorTypes);
1884 
1885  // And now the parameter types...
1886  for (int j = 0; j < ftype->GetNumParameters(); ++j)
1887  lGetExportedTypes(ftype->GetParameterType(j), exportedStructTypes,
1888  exportedEnumTypes, exportedVectorTypes);
1889  }
1890  else
1891  Assert(CastType<AtomicType>(type) != NULL);
1892 }
1893 
1894 
1895 /** Given a set of functions, return the set of structure and vector types
1896  present in the parameters to them.
1897  */
1898 static void
1899 lGetExportedParamTypes(const std::vector<Symbol *> &funcs,
1900  std::vector<const StructType *> *exportedStructTypes,
1901  std::vector<const EnumType *> *exportedEnumTypes,
1902  std::vector<const VectorType *> *exportedVectorTypes) {
1903  for (unsigned int i = 0; i < funcs.size(); ++i) {
1904  const FunctionType *ftype = CastType<FunctionType>(funcs[i]->type);
1905  // Handle the return type
1906  lGetExportedTypes(ftype->GetReturnType(), exportedStructTypes,
1907  exportedEnumTypes, exportedVectorTypes);
1908 
1909  // And now the parameter types...
1910  for (int j = 0; j < ftype->GetNumParameters(); ++j)
1911  lGetExportedTypes(ftype->GetParameterType(j), exportedStructTypes,
1912  exportedEnumTypes, exportedVectorTypes);
1913  }
1914 }
1915 
1916 
1917 static void
1918 lPrintFunctionDeclarations(FILE *file, const std::vector<Symbol *> &funcs,
1919  bool useExternC=1, bool rewriteForDispatch=false) {
1920  if (useExternC)
1921  fprintf(file, "#if defined(__cplusplus) && (! defined(__ISPC_NO_EXTERN_C) || !__ISPC_NO_EXTERN_C )\nextern \"C\" {\n#endif // __cplusplus\n");
1922  // fprintf(file, "#ifdef __cplusplus\nextern \"C\" {\n#endif // __cplusplus\n");
1923  for (unsigned int i = 0; i < funcs.size(); ++i) {
1924  const FunctionType *ftype = CastType<FunctionType>(funcs[i]->type);
1925  Assert(ftype);
1926  std::string decl;
1927  if (rewriteForDispatch) {
1928  decl = ftype->GetCDeclarationForDispatch(funcs[i]->name);
1929  }
1930  else {
1931  decl = ftype->GetCDeclaration(funcs[i]->name);
1932  }
1933  fprintf(file, " extern %s;\n", decl.c_str());
1934  }
1935  if (useExternC)
1936 
1937  fprintf(file, "#if defined(__cplusplus) && (! defined(__ISPC_NO_EXTERN_C) || !__ISPC_NO_EXTERN_C )\n} /* end extern C */\n#endif // __cplusplus\n");
1938  // fprintf(file, "#ifdef __cplusplus\n} /* end extern C */\n#endif // __cplusplus\n");
1939 }
1940 
1941 
1942 
1943 
1944 
1945 
1946 static bool
1947 lIsExported(const Symbol *sym) {
1948  const FunctionType *ft = CastType<FunctionType>(sym->type);
1949  Assert(ft);
1950  return ft->isExported;
1951 }
1952 
1953 
1954 static bool
1955 lIsExternC(const Symbol *sym) {
1956  const FunctionType *ft = CastType<FunctionType>(sym->type);
1957  Assert(ft);
1958  return ft->isExternC;
1959 }
1960 
1961 
1962 static void
1963 lUnescapeStringInPlace(std::string& str) {
1964  // There are many more escape sequences, but since this is a path,
1965  // we can get away with only supporting the basic ones (i.e. no
1966  // octal, hexadecimal or unicode values).
1967  for (std::string::iterator it = str.begin(); it != str.end(); ++it) {
1968  size_t pos = it - str.begin();
1969  std::string::iterator next = it + 1;
1970  if (*it == '\\' && next != str.end()) {
1971  switch (*next) {
1972 #define UNESCAPE_SEQ(c, esc) case c: *it = esc; str.erase(next); it = str.begin() + pos; break
1973  UNESCAPE_SEQ('\'', '\'');
1974  UNESCAPE_SEQ('?', '?');
1975  UNESCAPE_SEQ('\\', '\\');
1976  UNESCAPE_SEQ('a', '\a');
1977  UNESCAPE_SEQ('b', '\b');
1978  UNESCAPE_SEQ('f', '\f');
1979  UNESCAPE_SEQ('n', '\n');
1980  UNESCAPE_SEQ('r', '\r');
1981  UNESCAPE_SEQ('t', '\t');
1982  UNESCAPE_SEQ('v', '\v');
1983 #undef UNESCAPE_SEQ
1984  }
1985  }
1986  }
1987 }
1988 
1989 
1990 bool
1991 Module::writeDeps(const char *fn, bool generateMakeRule, const char *tn, const char *sn) {
1992  if (fn) // We may be passed nullptr for stdout output.
1993  std::cout << "writing dependencies to file " << fn << std::endl;
1994  FILE *file = fn ? fopen(fn,"w") : stdout;
1995  if (!file) {
1996  perror("fopen");
1997  return false;
1998  }
1999 
2000  if (generateMakeRule) {
2001  fprintf(file,"%s:", tn);
2002  if (sn) // Rules always emit source first.
2003  fprintf(file," %s \\\n",sn);
2004  std::string unescaped;
2005  for (std::set<std::string>::const_iterator it=registeredDependencies.begin();
2006  it != registeredDependencies.end();
2007  ++it) {
2008  unescaped = *it; // As this is preprocessor output, paths come escaped.
2009  lUnescapeStringInPlace(unescaped);
2010  if (sn && 0 == strcmp(sn, unescaped.c_str())) // If source has been passed, it's already emitted.
2011  continue;
2012  fprintf(file," %s \\\n",unescaped.c_str());
2013  }
2014  } else {
2015  for (std::set<std::string>::const_iterator it=registeredDependencies.begin();
2016  it != registeredDependencies.end();
2017  ++it)
2018  fprintf(file,"%s\n",it->c_str());
2019  }
2020  return true;
2021 }
2022 
2023 
2024 std::string emitOffloadParamStruct(const std::string &paramStructName,
2025  const Symbol *sym,
2026  const FunctionType *fct)
2027 {
2028  std::stringstream out;
2029  out << "struct " << paramStructName << " {" << std::endl;
2030 
2031  for (int i=0;i<fct->GetNumParameters();i++) {
2032  const Type *orgParamType = fct->GetParameterType(i);
2033  if (orgParamType->IsPointerType() || orgParamType->IsArrayType()) {
2034  /* we're passing pointers separately -- no pointers in that struct... */
2035  continue;
2036  }
2037 
2038  // const reference parameters can be passed as copies.
2039  const Type *paramType;
2040  if (orgParamType->IsReferenceType()) {
2041  if (!orgParamType->IsConstType()) {
2042  Error(sym->pos,"When emitting offload-stubs, \"export\"ed functions cannot have non-const reference-type parameters.\n");
2043  }
2044  const ReferenceType *refType = static_cast<const ReferenceType *>(orgParamType);
2045  paramType = refType->GetReferenceTarget()->GetAsNonConstType();
2046  } else {
2047  paramType = orgParamType->GetAsNonConstType();
2048  }
2049  std::string paramName = fct->GetParameterName(i);
2050  std::string paramTypeName = paramType->GetString();
2051 
2052  std::string tmpArgDecl = paramType->GetCDeclaration(paramName);
2053  out << " " << tmpArgDecl << ";" << std::endl;
2054  }
2055 
2056  out << "};" << std::endl;
2057  return out.str();
2058 }
2059 
2060 bool
2061 Module::writeDevStub(const char *fn)
2062 {
2063  FILE *file = fopen(fn, "w");
2064  if (!file) {
2065  perror("fopen");
2066  return false;
2067  }
2068  fprintf(file, "//\n// %s\n// (device stubs automatically generated by the ispc compiler.)\n", fn);
2069  fprintf(file, "// DO NOT EDIT THIS FILE.\n//\n\n");
2070  fprintf(file,"#include \"ispc/dev/offload.h\"\n\n");
2071 
2072  fprintf(file, "#include <stdint.h>\n\n");
2073 
2074  // Collect single linear arrays of the *exported* functions (we'll
2075  // treat those as "__kernel"s in IVL -- "extern" functions will only
2076  // be used for dev-dev function calls; only "export" functions will
2077  // get exported to the host
2078  std::vector<Symbol *> exportedFuncs;
2079  m->symbolTable->GetMatchingFunctions(lIsExported, &exportedFuncs);
2080 
2081  // Get all of the struct, vector, and enumerant types used as function
2082  // parameters. These vectors may have repeats.
2083  std::vector<const StructType *> exportedStructTypes;
2084  std::vector<const EnumType *> exportedEnumTypes;
2085  std::vector<const VectorType *> exportedVectorTypes;
2086  lGetExportedParamTypes(exportedFuncs, &exportedStructTypes,
2087  &exportedEnumTypes, &exportedVectorTypes);
2088 
2089  // And print them
2090  lEmitVectorTypedefs(exportedVectorTypes, file);
2091  lEmitEnumDecls(exportedEnumTypes, file);
2092  lEmitStructDecls(exportedStructTypes, file);
2093 
2094  fprintf(file, "#ifdef __cplusplus\n");
2095  fprintf(file, "namespace ispc {\n");
2096  fprintf(file, "#endif // __cplusplus\n");
2097 
2098  fprintf(file, "\n");
2099  fprintf(file, "///////////////////////////////////////////////////////////////////////////\n");
2100  fprintf(file, "// Functions exported from ispc code\n");
2101  fprintf(file, "// (so the dev stub knows what to call)\n");
2102  fprintf(file, "///////////////////////////////////////////////////////////////////////////\n");
2103  lPrintFunctionDeclarations(file, exportedFuncs, true);
2104 
2105  fprintf(file, "#ifdef __cplusplus\n");
2106  fprintf(file, "}/* end namespace */\n");
2107  fprintf(file, "#endif // __cplusplus\n");
2108 
2109  fprintf(file, "\n");
2110  fprintf(file, "///////////////////////////////////////////////////////////////////////////\n");
2111  fprintf(file, "// actual dev stubs\n");
2112  fprintf(file, "///////////////////////////////////////////////////////////////////////////\n");
2113 
2114  fprintf(file, "// note(iw): due to some linking issues offload stubs *only* work under C++\n");
2115  fprintf(file, "extern \"C\" {\n\n");
2116  for (unsigned int i = 0; i < exportedFuncs.size(); ++i) {
2117  const Symbol *sym = exportedFuncs[i];
2118  Assert(sym);
2119  const FunctionType *fct = CastType<FunctionType>(sym->type);
2120  Assert(fct);
2121 
2122  if (!fct->GetReturnType()->IsVoidType()) {
2123  //Error(sym->pos,"When emitting offload-stubs, \"export\"ed functions cannot have non-void return types.\n");
2124  Warning(sym->pos,"When emitting offload-stubs, ignoring \"export\"ed function with non-void return types.\n");
2125  continue;
2126  }
2127 
2128  // -------------------------------------------------------
2129  // first, emit a struct that holds the parameters
2130  // -------------------------------------------------------
2131  std::string paramStructName = std::string("__ispc_dev_stub_")+sym->name;
2132  std::string paramStruct = emitOffloadParamStruct(paramStructName,sym,fct);
2133  fprintf(file,"%s\n",paramStruct.c_str());
2134  // -------------------------------------------------------
2135  // then, emit a fct stub that unpacks the parameters and pointers
2136  // -------------------------------------------------------
2137  fprintf(file,"void __ispc_dev_stub_%s(\n"
2138  " uint32_t in_BufferCount,\n"
2139  " void** in_ppBufferPointers,\n"
2140  " uint64_t* in_pBufferLengths,\n"
2141  " void* in_pMiscData,\n"
2142  " uint16_t in_MiscDataLength,\n"
2143  " void* in_pReturnValue,\n"
2144  " uint16_t in_ReturnValueLength)\n",
2145  sym->name.c_str()
2146  );
2147  fprintf(file,"{\n");
2148  fprintf(file," struct %s args;\n memcpy(&args,in_pMiscData,sizeof(args));\n",
2149  paramStructName.c_str());
2150  std::stringstream funcall;
2151 
2152  funcall << "ispc::" << sym->name << "(";
2153  for (int i=0;i<fct->GetNumParameters();i++) {
2154  // get param type and make it non-const, so we can write while unpacking
2155  // const Type *paramType = fct->GetParameterType(i)->GetAsNonConstType();
2156  const Type *paramType;// = fct->GetParameterType(i)->GetAsNonConstType();
2157  const Type *orgParamType = fct->GetParameterType(i);
2158  if (orgParamType->IsReferenceType()) {
2159  if (!orgParamType->IsConstType()) {
2160  Error(sym->pos,"When emitting offload-stubs, \"export\"ed functions cannot have non-const reference-type parameters.\n");
2161  }
2162  const ReferenceType *refType = static_cast<const ReferenceType *>(orgParamType);
2163  paramType = refType->GetReferenceTarget()->GetAsNonConstType();
2164  } else {
2165  paramType = orgParamType->GetAsNonConstType();
2166  }
2167 
2168  std::string paramName = fct->GetParameterName(i);
2169  std::string paramTypeName = paramType->GetString();
2170 
2171  if (i) funcall << ", ";
2172  std::string tmpArgName = std::string("_")+paramName;
2173  if (paramType->IsPointerType() || paramType->IsArrayType()) {
2174  std::string tmpArgDecl = paramType->GetCDeclaration(tmpArgName);
2175  fprintf(file," %s;\n",
2176  tmpArgDecl.c_str());
2177  fprintf(file," (void *&)%s = ispc_dev_translate_pointer(*in_ppBufferPointers++);\n",
2178  tmpArgName.c_str());
2179  funcall << tmpArgName;
2180  } else {
2181  funcall << "args." << paramName;
2182  }
2183  }
2184  funcall << ");";
2185  fprintf(file," %s\n",funcall.str().c_str());
2186  fprintf(file,"}\n\n");
2187  }
2188 
2189  // end extern "C"
2190  fprintf(file, "}/* end extern C */\n");
2191 
2192  fclose(file);
2193  return true;
2194 }
2195 
2196 
2197 
2198 bool
2199 Module::writeHostStub(const char *fn)
2200 {
2201  FILE *file = fopen(fn, "w");
2202  if (!file) {
2203  perror("fopen");
2204  return false;
2205  }
2206  fprintf(file, "//\n// %s\n// (device stubs automatically generated by the ispc compiler.)\n", fn);
2207  fprintf(file, "// DO NOT EDIT THIS FILE.\n//\n\n");
2208  fprintf(file,"#include \"ispc/host/offload.h\"\n\n");
2209  fprintf(file,"// note(iw): Host stubs do not get extern C linkage -- dev-side already uses that for the same symbols.\n\n");
2210  //fprintf(file,"#ifdef __cplusplus\nextern \"C\" {\n#endif // __cplusplus\n");
2211 
2212  fprintf(file, "#ifdef __cplusplus\nnamespace ispc {\n#endif // __cplusplus\n\n");
2213 
2214  // Collect single linear arrays of the *exported* functions (we'll
2215  // treat those as "__kernel"s in IVL -- "extern" functions will only
2216  // be used for dev-dev function calls; only "export" functions will
2217  // get exported to the host
2218  std::vector<Symbol *> exportedFuncs;
2219  m->symbolTable->GetMatchingFunctions(lIsExported, &exportedFuncs);
2220 
2221  // Get all of the struct, vector, and enumerant types used as function
2222  // parameters. These vectors may have repeats.
2223  std::vector<const StructType *> exportedStructTypes;
2224  std::vector<const EnumType *> exportedEnumTypes;
2225  std::vector<const VectorType *> exportedVectorTypes;
2226  lGetExportedParamTypes(exportedFuncs, &exportedStructTypes,
2227  &exportedEnumTypes, &exportedVectorTypes);
2228 
2229  // And print them
2230  lEmitVectorTypedefs(exportedVectorTypes, file);
2231  lEmitEnumDecls(exportedEnumTypes, file);
2232  lEmitStructDecls(exportedStructTypes, file);
2233 
2234  fprintf(file, "\n");
2235  fprintf(file, "///////////////////////////////////////////////////////////////////////////\n");
2236  fprintf(file, "// host-side stubs for dev-side ISPC fucntion(s)\n");
2237  fprintf(file, "///////////////////////////////////////////////////////////////////////////\n");
2238  for (unsigned int i = 0; i < exportedFuncs.size(); ++i) {
2239  const Symbol *sym = exportedFuncs[i];
2240  Assert(sym);
2241  const FunctionType *fct = CastType<FunctionType>(sym->type);
2242  Assert(fct);
2243 
2244  if (!fct->GetReturnType()->IsVoidType()) {
2245  Warning(sym->pos,"When emitting offload-stubs, ignoring \"export\"ed function with non-void return types.\n");
2246  continue;
2247  }
2248 
2249 
2250 
2251  // -------------------------------------------------------
2252  // first, emit a struct that holds the parameters
2253  // -------------------------------------------------------
2254  std::string paramStructName = std::string("__ispc_dev_stub_")+sym->name;
2255  std::string paramStruct = emitOffloadParamStruct(paramStructName,sym,fct);
2256  fprintf(file,"%s\n",paramStruct.c_str());
2257  // -------------------------------------------------------
2258  // then, emit a fct stub that unpacks the parameters and pointers
2259  // -------------------------------------------------------
2260 
2261  std::string decl = fct->GetCDeclaration(sym->name);
2262  fprintf(file, "extern %s {\n", decl.c_str());
2263  int numPointers = 0;
2264  fprintf(file, " %s __args;\n",paramStructName.c_str());
2265 
2266  // ------------------------------------------------------------------
2267  // write args, and save pointers for later
2268  // ------------------------------------------------------------------
2269  std::stringstream pointerArgs;
2270  for (int i=0;i<fct->GetNumParameters();i++) {
2271  const Type *orgParamType = fct->GetParameterType(i);
2272  std::string paramName = fct->GetParameterName(i);
2273  if (orgParamType->IsPointerType() || orgParamType->IsArrayType()) {
2274  /* we're passing pointers separately -- no pointers in that struct... */
2275  if (numPointers)
2276  pointerArgs << ",";
2277  pointerArgs << "(void*)" << paramName;
2278  numPointers++;
2279  continue;
2280  }
2281 
2282  fprintf(file," __args.%s = %s;\n",
2283  paramName.c_str(),paramName.c_str());
2284  }
2285  // ------------------------------------------------------------------
2286  // writer pointer list
2287  // ------------------------------------------------------------------
2288  if (numPointers == 0)
2289  pointerArgs << "NULL";
2290  fprintf(file," void *ptr_args[] = { %s };\n" ,pointerArgs.str().c_str());
2291 
2292  // ------------------------------------------------------------------
2293  // ... and call the kernel with those args
2294  // ------------------------------------------------------------------
2295  fprintf(file," static ispc_kernel_handle_t kernel_handle = NULL;\n");
2296  fprintf(file," if (!kernel_handle) kernel_handle = ispc_host_get_kernel_handle(\"__ispc_dev_stub_%s\");\n",
2297  sym->name.c_str());
2298  fprintf(file," assert(kernel_handle);\n");
2299  fprintf(file,
2300  " ispc_host_call_kernel(kernel_handle,\n"
2301  " &__args, sizeof(__args),\n"
2302  " ptr_args,%i);\n",
2303  numPointers);
2304  fprintf(file,"}\n\n");
2305  }
2306 
2307  // end extern "C"
2308  fprintf(file, "#ifdef __cplusplus\n");
2309  fprintf(file, "}/* namespace */\n");
2310  fprintf(file, "#endif // __cplusplus\n");
2311  // fprintf(file, "#ifdef __cplusplus\n");
2312  // fprintf(file, "}/* end extern C */\n");
2313  // fprintf(file, "#endif // __cplusplus\n");
2314 
2315  fclose(file);
2316  return true;
2317 }
2318 
2319 
2320 bool
2321 Module::writeHeader(const char *fn) {
2322  FILE *f = fopen(fn, "w");
2323  if (!f) {
2324  perror("fopen");
2325  return false;
2326  }
2327  fprintf(f, "//\n// %s\n// (Header automatically generated by the ispc compiler.)\n", fn);
2328  fprintf(f, "// DO NOT EDIT THIS FILE.\n//\n\n");
2329 
2330  // Create a nice guard string from the filename, turning any
2331  // non-number/letter characters into underbars
2332  std::string guard = "ISPC_";
2333  const char *p = fn;
2334  while (*p) {
2335  if (isdigit(*p))
2336  guard += *p;
2337  else if (isalpha(*p))
2338  guard += toupper(*p);
2339  else
2340  guard += "_";
2341  ++p;
2342  }
2343  fprintf(f, "#ifndef %s\n#define %s\n\n", guard.c_str(), guard.c_str());
2344 
2345  fprintf(f, "#include <stdint.h>\n\n");
2346 
2347  if (g->emitInstrumentation) {
2348  fprintf(f, "#define ISPC_INSTRUMENTATION 1\n");
2349  fprintf(f, "#if defined(__cplusplus) && (! defined(__ISPC_NO_EXTERN_C) || !__ISPC_NO_EXTERN_C )\nextern \"C\" {\n#endif // __cplusplus\n");
2350  fprintf(f, " void ISPCInstrument(const char *fn, const char *note, int line, uint64_t mask);\n");
2351  fprintf(f, "#if defined(__cplusplus) && (! defined(__ISPC_NO_EXTERN_C) || !__ISPC_NO_EXTERN_C )\n} /* end extern C */\n#endif // __cplusplus\n");
2352  }
2353 
2354  // end namespace
2355  fprintf(f, "\n");
2356  fprintf(f, "\n#ifdef __cplusplus\nnamespace ispc { /* namespace */\n#endif // __cplusplus\n");
2357 
2358 
2359  // Collect single linear arrays of the exported and extern "C"
2360  // functions
2361  std::vector<Symbol *> exportedFuncs, externCFuncs;
2362  m->symbolTable->GetMatchingFunctions(lIsExported, &exportedFuncs);
2363  m->symbolTable->GetMatchingFunctions(lIsExternC, &externCFuncs);
2364 
2365  // Get all of the struct, vector, and enumerant types used as function
2366  // parameters. These vectors may have repeats.
2367  std::vector<const StructType *> exportedStructTypes;
2368  std::vector<const EnumType *> exportedEnumTypes;
2369  std::vector<const VectorType *> exportedVectorTypes;
2370  lGetExportedParamTypes(exportedFuncs, &exportedStructTypes,
2371  &exportedEnumTypes, &exportedVectorTypes);
2372  lGetExportedParamTypes(externCFuncs, &exportedStructTypes,
2373  &exportedEnumTypes, &exportedVectorTypes);
2374 
2375  // Go through the explicitly exported types
2376  for (int i = 0; i < (int)exportedTypes.size(); ++i) {
2377  if (const StructType *st = CastType<StructType>(exportedTypes[i].first))
2378  exportedStructTypes.push_back(st->GetAsUniformType());
2379  else if (const EnumType *et = CastType<EnumType>(exportedTypes[i].first))
2380  exportedEnumTypes.push_back(et->GetAsUniformType());
2381  else if (const VectorType *vt = CastType<VectorType>(exportedTypes[i].first))
2382  exportedVectorTypes.push_back(vt->GetAsUniformType());
2383  else
2384  FATAL("Unexpected type in export list");
2385  }
2386 
2387  // And print them
2388  lEmitVectorTypedefs(exportedVectorTypes, f);
2389  lEmitEnumDecls(exportedEnumTypes, f);
2390  lEmitStructDecls(exportedStructTypes, f);
2391 
2392  // emit function declarations for exported stuff...
2393  if (exportedFuncs.size() > 0) {
2394  fprintf(f, "\n");
2395  fprintf(f, "///////////////////////////////////////////////////////////////////////////\n");
2396  fprintf(f, "// Functions exported from ispc code\n");
2397  fprintf(f, "///////////////////////////////////////////////////////////////////////////\n");
2398  lPrintFunctionDeclarations(f, exportedFuncs);
2399  }
2400 #if 0
2401  if (externCFuncs.size() > 0) {
2402  fprintf(f, "\n");
2403  fprintf(f, "///////////////////////////////////////////////////////////////////////////\n");
2404  fprintf(f, "// External C functions used by ispc code\n");
2405  fprintf(f, "///////////////////////////////////////////////////////////////////////////\n");
2406  lPrintFunctionDeclarations(f, externCFuncs);
2407  }
2408 #endif
2409 
2410  // end namespace
2411  fprintf(f, "\n");
2412  fprintf(f, "\n#ifdef __cplusplus\n} /* namespace */\n#endif // __cplusplus\n");
2413 
2414  // end guard
2415  fprintf(f, "\n#endif // %s\n", guard.c_str());
2416 
2417  fclose(f);
2418  return true;
2419 }
2420 
2426  bool Emit4;
2427  bool Emit8;
2428  bool Emit16;
2429  FILE *file;
2430  const char *fn;
2431 };
2432 
2433 bool
2435  FILE *f = DHI->file;
2436 
2437  if (DHI->EmitFrontMatter) {
2438  fprintf(f, "//\n// %s\n// (Header automatically generated by the ispc compiler.)\n", DHI->fn);
2439  fprintf(f, "// DO NOT EDIT THIS FILE.\n//\n\n");
2440  }
2441  // Create a nice guard string from the filename, turning any
2442  // non-number/letter characters into underbars
2443  std::string guard = "ISPC_";
2444  const char *p = DHI->fn;
2445  while (*p) {
2446  if (isdigit(*p))
2447  guard += *p;
2448  else if (isalpha(*p))
2449  guard += toupper(*p);
2450  else
2451  guard += "_";
2452  ++p;
2453  }
2454  if (DHI->EmitFrontMatter) {
2455  fprintf(f, "#ifndef %s\n#define %s\n\n", guard.c_str(), guard.c_str());
2456 
2457  fprintf(f, "#include <stdint.h>\n\n");
2458 
2459 
2460  if (g->emitInstrumentation) {
2461  fprintf(f, "#define ISPC_INSTRUMENTATION 1\n");
2462  fprintf(f, "#if defined(__cplusplus) && (! defined(__ISPC_NO_EXTERN_C) || !__ISPC_NO_EXTERN_C )\nextern \"C\" {\n#endif // __cplusplus\n");
2463  fprintf(f, " void ISPCInstrument(const char *fn, const char *note, int line, uint64_t mask);\n");
2464  fprintf(f, "#if defined(__cplusplus) && (! defined(__ISPC_NO_EXTERN_C) || !__ISPC_NO_EXTERN_C )\n} /* end extern C */\n#endif // __cplusplus\n");
2465  }
2466 
2467  // end namespace
2468  fprintf(f, "\n");
2469  fprintf(f, "\n#ifdef __cplusplus\nnamespace ispc { /* namespace */\n#endif // __cplusplus\n\n");
2470  DHI->EmitFrontMatter = false;
2471  }
2472 
2473 
2474  // Collect single linear arrays of the exported and extern "C"
2475  // functions
2476  std::vector<Symbol *> exportedFuncs, externCFuncs;
2477  m->symbolTable->GetMatchingFunctions(lIsExported, &exportedFuncs);
2478  m->symbolTable->GetMatchingFunctions(lIsExternC, &externCFuncs);
2479 
2480  int programCount = g->target->getVectorWidth();
2481 
2482  if ((DHI->Emit4 && (programCount == 4)) ||
2483  (DHI->Emit8 && (programCount == 8)) ||
2484  (DHI->Emit16 && (programCount == 16))) {
2485  // Get all of the struct, vector, and enumerant types used as function
2486  // parameters. These vectors may have repeats.
2487  std::vector<const StructType *> exportedStructTypes;
2488  std::vector<const EnumType *> exportedEnumTypes;
2489  std::vector<const VectorType *> exportedVectorTypes;
2490  lGetExportedParamTypes(exportedFuncs, &exportedStructTypes,
2491  &exportedEnumTypes, &exportedVectorTypes);
2492  lGetExportedParamTypes(externCFuncs, &exportedStructTypes,
2493  &exportedEnumTypes, &exportedVectorTypes);
2494 
2495  // Go through the explicitly exported types
2496  for (int i = 0; i < (int)exportedTypes.size(); ++i) {
2497  if (const StructType *st = CastType<StructType>(exportedTypes[i].first))
2498  exportedStructTypes.push_back(st->GetAsUniformType());
2499  else if (const EnumType *et = CastType<EnumType>(exportedTypes[i].first))
2500  exportedEnumTypes.push_back(et->GetAsUniformType());
2501  else if (const VectorType *vt = CastType<VectorType>(exportedTypes[i].first))
2502  exportedVectorTypes.push_back(vt->GetAsUniformType());
2503  else
2504  FATAL("Unexpected type in export list");
2505  }
2506 
2507 
2508  // And print them
2509  if (DHI->EmitUnifs) {
2510  lEmitVectorTypedefs(exportedVectorTypes, f);
2511  lEmitEnumDecls(exportedEnumTypes, f);
2512  }
2513  lEmitStructDecls(exportedStructTypes, f, DHI->EmitUnifs);
2514 
2515  // Update flags
2516  DHI->EmitUnifs = false;
2517  if (programCount == 4) {
2518  DHI->Emit4 = false;
2519  }
2520  else if (programCount == 8) {
2521  DHI->Emit8 = false;
2522  }
2523  else if (programCount == 16) {
2524  DHI->Emit16 = false;
2525  }
2526  }
2527  if (DHI->EmitFuncs) {
2528  // emit function declarations for exported stuff...
2529  if (exportedFuncs.size() > 0) {
2530  fprintf(f, "\n");
2531  fprintf(f, "///////////////////////////////////////////////////////////////////////////\n");
2532  fprintf(f, "// Functions exported from ispc code\n");
2533  fprintf(f, "///////////////////////////////////////////////////////////////////////////\n");
2534  lPrintFunctionDeclarations(f, exportedFuncs, 1, true);
2535  fprintf(f, "\n");
2536  }
2537  DHI->EmitFuncs = false;
2538  }
2539 
2540  if (DHI->EmitBackMatter) {
2541  // end namespace
2542  fprintf(f, "\n");
2543  fprintf(f, "\n#ifdef __cplusplus\n} /* namespace */\n#endif // __cplusplus\n");
2544 
2545  // end guard
2546  fprintf(f, "\n#endif // %s\n", guard.c_str());
2547  DHI->EmitBackMatter = false;
2548  }
2549 
2550  return true;
2551 }
2552 
2553 void
2554 Module::execPreprocessor(const char *infilename, llvm::raw_string_ostream *ostream) const
2555 {
2556  clang::CompilerInstance inst;
2557 
2558  llvm::raw_fd_ostream stderrRaw(2, false);
2559 
2560  clang::DiagnosticOptions *diagOptions = new clang::DiagnosticOptions();
2561  clang::TextDiagnosticPrinter *diagPrinter =
2562  new clang::TextDiagnosticPrinter(stderrRaw, diagOptions);
2563 
2564  llvm::IntrusiveRefCntPtr<clang::DiagnosticIDs> diagIDs(new clang::DiagnosticIDs);
2565  clang::DiagnosticsEngine *diagEngine =
2566  new clang::DiagnosticsEngine(diagIDs, diagOptions, diagPrinter);
2567 
2568  inst.setDiagnostics(diagEngine);
2569 
2570  inst.createFileManager();
2571 
2572 #if ISPC_LLVM_VERSION <= ISPC_LLVM_3_4 // 3.2, 3.3, 3.4
2573  clang::TargetOptions &options = inst.getTargetOpts();
2574 #else // LLVM 3.5+
2575  const std::shared_ptr< clang::TargetOptions > &options =
2576  std::make_shared< clang::TargetOptions >(inst.getTargetOpts());
2577 #endif
2578 
2579  llvm::Triple triple(module->getTargetTriple());
2580  if (triple.getTriple().empty()) {
2581  triple.setTriple(llvm::sys::getDefaultTargetTriple());
2582  }
2583 
2584 #if ISPC_LLVM_VERSION <= ISPC_LLVM_3_4 // 3.2, 3.3, 3.4
2585  options.Triple = triple.getTriple();
2586 #else // LLVM 3.5+
2587  options->Triple = triple.getTriple();
2588 #endif
2589 
2590 #if ISPC_LLVM_VERSION == ISPC_LLVM_3_2 // 3.2
2591  clang::TargetInfo *target =
2592  clang::TargetInfo::CreateTargetInfo(inst.getDiagnostics(), options);
2593 #elif ISPC_LLVM_VERSION <= ISPC_LLVM_3_4 // 3.3, 3.4
2594  clang::TargetInfo *target =
2595  clang::TargetInfo::CreateTargetInfo(inst.getDiagnostics(), &options);
2596 #else // LLVM 3.5+
2597  clang::TargetInfo *target =
2598  clang::TargetInfo::CreateTargetInfo(inst.getDiagnostics(), options);
2599 #endif
2600 
2601  inst.setTarget(target);
2602  inst.createSourceManager(inst.getFileManager());
2603 #if ISPC_LLVM_VERSION < ISPC_LLVM_5_0
2604  clang::FrontendInputFile inputFile(infilename, clang::IK_None);
2605 #else // LLVM 5.0+
2606  clang::FrontendInputFile inputFile(infilename, clang::InputKind::Unknown);
2607 #endif
2608  inst.InitializeSourceManager(inputFile);
2609 
2610  // Don't remove comments in the preprocessor, so that we can accurately
2611  // track the source file position by handling them ourselves.
2612  inst.getPreprocessorOutputOpts().ShowComments = 1;
2613 
2614 #if ISPC_LLVM_VERSION >= ISPC_LLVM_3_3 // LLVM 3.3+
2615  inst.getPreprocessorOutputOpts().ShowCPP = 1;
2616 #endif
2617 
2618  clang::HeaderSearchOptions &headerOpts = inst.getHeaderSearchOpts();
2619  headerOpts.UseBuiltinIncludes = 0;
2620  headerOpts.UseStandardSystemIncludes = 0;
2621  headerOpts.UseStandardCXXIncludes = 0;
2622  if (g->debugPrint)
2623  headerOpts.Verbose = 1;
2624  for (int i = 0; i < (int)g->includePath.size(); ++i) {
2625  headerOpts.AddPath(g->includePath[i], clang::frontend::Angled,
2626 #if ISPC_LLVM_VERSION == ISPC_LLVM_3_2
2627  true /* is user supplied */,
2628 #endif
2629  false /* not a framework */,
2630  true /* ignore sys root */);
2631  }
2632 
2633  clang::PreprocessorOptions &opts = inst.getPreprocessorOpts();
2634 
2635  // Add defs for ISPC and PI
2636  opts.addMacroDef("ISPC");
2637  opts.addMacroDef("PI=3.1415926535");
2638 
2639  // Add #define for current compilation target
2640  char targetMacro[128];
2641  sprintf(targetMacro, "ISPC_TARGET_%s", g->target->GetISAString());
2642  char *p = targetMacro;
2643  while (*p) {
2644  *p = toupper(*p);
2645  if (*p == '-') *p = '_';
2646  ++p;
2647  }
2648  opts.addMacroDef(targetMacro);
2649 
2650  if (g->target->is32Bit())
2651  opts.addMacroDef("ISPC_POINTER_SIZE=32");
2652  else
2653  opts.addMacroDef("ISPC_POINTER_SIZE=64");
2654 
2655  if (g->target->hasHalf())
2656  opts.addMacroDef("ISPC_TARGET_HAS_HALF");
2657  if (g->target->hasRand())
2658  opts.addMacroDef("ISPC_TARGET_HAS_RAND");
2659  if (g->target->hasTranscendentals())
2660  opts.addMacroDef("ISPC_TARGET_HAS_TRANSCENDENTALS");
2661  if (g->opt.forceAlignedMemory)
2662  opts.addMacroDef("ISPC_FORCE_ALIGNED_MEMORY");
2663 
2664  opts.addMacroDef("ISPC_MAJOR_VERSION=1");
2665  opts.addMacroDef("ISPC_MINOR_VERSION=4");
2666 
2667  if (g->includeStdlib) {
2668  if (g->opt.disableAsserts)
2669  opts.addMacroDef("assert(x)=");
2670  else
2671  opts.addMacroDef("assert(x)=__assert(#x, x)");
2672  }
2673 
2674  for (unsigned int i = 0; i < g->cppArgs.size(); ++i) {
2675  // Sanity check--should really begin with -D
2676  if (g->cppArgs[i].substr(0,2) == "-D") {
2677  opts.addMacroDef(g->cppArgs[i].substr(2));
2678  }
2679  }
2680 #ifdef ISPC_NVPTX_ENABLED
2681  if (g->target->getISA() == Target::NVPTX)
2682  {
2683  opts.addMacroDef("__NVPTX__");
2684  opts.addMacroDef("programIndex=__programIndex()");
2685 #if 1
2686  opts.addMacroDef("cif=if");
2687  opts.addMacroDef("cfor=for");
2688  opts.addMacroDef("cwhile=while");
2689  opts.addMacroDef("ccontinue=continue");
2690  opts.addMacroDef("cdo=do");
2691 #endif
2692  opts.addMacroDef("taskIndex0=__taskIndex0()");
2693  opts.addMacroDef("taskIndex1=__taskIndex1()");
2694  opts.addMacroDef("taskIndex2=__taskIndex2()");
2695  opts.addMacroDef("taskIndex=__taskIndex()");
2696  opts.addMacroDef("taskCount0=__taskCount0()");
2697  opts.addMacroDef("taskCount1=__taskCount1()");
2698  opts.addMacroDef("taskCount2=__taskCount2()");
2699  opts.addMacroDef("taskCount=__taskCount()");
2700  }
2701 #endif /* ISPC_NVPTX_ENABLED */
2702 
2703  inst.getLangOpts().LineComment = 1;
2704 
2705 #if ISPC_LLVM_VERSION >= ISPC_LLVM_3_5 /* 3.5+ */
2706  inst.createPreprocessor(clang::TU_Complete);
2707 #else
2708  inst.createPreprocessor();
2709 #endif
2710 
2711  diagPrinter->BeginSourceFile(inst.getLangOpts(), &inst.getPreprocessor());
2712  clang::DoPrintPreprocessedInput(inst.getPreprocessor(),
2713  ostream, inst.getPreprocessorOutputOpts());
2714  diagPrinter->EndSourceFile();
2715 }
2716 
2717 
2718 // Given an output filename of the form "foo.obj", and an ISA name like
2719 // "avx", return a string with the ISA name inserted before the original
2720 // filename's suffix, like "foo_avx.obj".
2721 static std::string
2722 lGetTargetFileName(const char *outFileName, const char *isaString, bool forceCXX) {
2723  char *targetOutFileName = new char[strlen(outFileName) + 16];
2724  if (strrchr(outFileName, '.') != NULL) {
2725  // Copy everything up to the last '.'
2726  int count = strrchr(outFileName, '.') - outFileName;
2727  strncpy(targetOutFileName, outFileName, count);
2728  targetOutFileName[count] = '\0';
2729 
2730  // Add the ISA name
2731  strcat(targetOutFileName, "_");
2732  strcat(targetOutFileName, isaString);
2733 
2734  // And finish with the original file suffix if it is not *-generic target
2735  if (!forceCXX)
2736  strcat(targetOutFileName, strrchr(outFileName, '.'));
2737  else
2738  strcat(targetOutFileName, ".cpp");
2739  }
2740  else {
2741  // Can't find a '.' in the filename, so just append the ISA suffix
2742  // to what we weregiven
2743  strcpy(targetOutFileName, outFileName);
2744  strcat(targetOutFileName, "_");
2745  strcat(targetOutFileName, isaString);
2746 
2747  // Append ".cpp" suffix to the original file if it is *-generic target
2748  if (forceCXX)
2749  strcat(targetOutFileName, ".cpp");
2750  }
2751  return targetOutFileName;
2752 }
2753 
2754 
2755 // Given a comma-delimited string with one or more compilation targets of
2756 // the form "sse2,avx-x2", return a vector of strings where each returned
2757 // string holds one of the targets from the given string.
2758 static std::vector<std::string>
2759 lExtractTargets(const char *target) {
2760  std::vector<std::string> targets;
2761  const char *tstart = target;
2762  bool done = false;
2763  while (!done) {
2764  const char *tend = strchr(tstart, ',');
2765  if (tend == NULL) {
2766  done = true;
2767  tend = strchr(tstart, '\0');
2768  }
2769  targets.push_back(std::string(tstart, tend));
2770  tstart = tend+1;
2771  }
2772  return targets;
2773 }
2774 
2775 
2776 static bool
2778  return s->exportedFunction != NULL;
2779 }
2780 
2781 
2782 // Small structure to hold pointers to the various different versions of a
2783 // llvm::Function that were compiled for different compilation target ISAs.
2786  for (int i = 0; i < Target::NUM_ISAS; ++i) {
2787  func[i] = NULL;
2788  FTs[i] = NULL;
2789  }
2790  }
2791  // The func array is indexed with the Target::ISA enumerant. Some
2792  // values may be NULL, indicating that the original function wasn't
2793  // compiled to the corresponding target ISA.
2794  llvm::Function *func[Target::NUM_ISAS];
2796 };
2797 
2798 
2799 // Given the symbol table for a module, return a map from function names to
2800 // FunctionTargetVariants for each function that was defined with the
2801 // 'export' qualifier in ispc.
2802 static void
2804  std::map<std::string, FunctionTargetVariants> &functions) {
2805  std::vector<Symbol *> syms;
2806  symbolTable->GetMatchingFunctions(lSymbolIsExported, &syms);
2807  for (unsigned int i = 0; i < syms.size(); ++i) {
2808  FunctionTargetVariants &ftv = functions[syms[i]->name];
2809  ftv.func[g->target->getISA()] = syms[i]->exportedFunction;
2810  ftv.FTs[g->target->getISA()] = CastType<FunctionType>(syms[i]->type);
2811  }
2812 }
2813 
2814 static llvm::FunctionType *
2816  llvm::Type *ptrToInt8Ty = llvm::Type::getInt8PtrTy(*g->ctx);
2817  llvm::FunctionType *resultFuncTy = NULL;
2818 
2819  for (int i = 0; i < Target::NUM_ISAS; ++i) {
2820  if (funcs.func[i] == NULL) {
2821  continue;
2822  }
2823  else {
2824  bool foundVarying = false;
2825  const FunctionType *ft = funcs.FTs[i];
2826  resultFuncTy = funcs.func[i]->getFunctionType();
2827 
2828  int numArgs = ft->GetNumParameters();
2829  llvm::SmallVector<llvm::Type *, 8> ftype;
2830  for (int j = 0; j < numArgs; ++j) {
2831  ftype.push_back(resultFuncTy->getParamType(j));
2832  }
2833 
2834  for (int j = 0; j < numArgs; ++j) {
2835  const Type *arg = ft->GetParameterType(j);
2836 
2837  if (arg->IsPointerType()) {
2838  const Type *baseType = CastType<PointerType>(arg)->GetBaseType();
2839  // For each varying type pointed to, swap the LLVM pointer type
2840  // with i8 * (as close as we can get to void *)
2841  if (baseType->IsVaryingType()) {
2842  ftype[j] = ptrToInt8Ty;
2843  foundVarying = true;
2844  }
2845  }
2846  }
2847  if (foundVarying) {
2848  resultFuncTy = llvm::FunctionType::get(resultFuncTy->getReturnType(), ftype, false);
2849  }
2850  }
2851  }
2852 
2853  // We should've found at least one variant here
2854  // or else something fishy is going on.
2855  Assert(resultFuncTy);
2856 
2857  return resultFuncTy;
2858 }
2859 
2860 /** Create the dispatch function for an exported ispc function.
2861  This function checks to see which vector ISAs the system the
2862  code is running on supports and calls out to the best available
2863  variant that was generated at compile time.
2864 
2865  @param module Module in which to create the dispatch function.
2866  @param setISAFunc Pointer to the __set_system_isa() function defined
2867  in builtins-dispatch.ll (which is linked into the
2868  given module before we get here.)
2869  @param systemBestISAPtr Pointer to the module-local __system_best_isa
2870  variable, which holds a value of the Target::ISA
2871  enumerant giving the most capable ISA that the
2872  system supports.
2873  @param name Name of the function for which we're generating a
2874  dispatch function
2875  @param funcs Target-specific variants of the exported function.
2876 */
2877 static void
2878 lCreateDispatchFunction(llvm::Module *module, llvm::Function *setISAFunc,
2879  llvm::Value *systemBestISAPtr, const std::string &name,
2880  FunctionTargetVariants &funcs) {
2881  // The llvm::Function pointers in funcs are pointers to functions in
2882  // different llvm::Modules, so we can't call them directly. Therefore,
2883  // we'll start by generating an 'extern' declaration of each one that
2884  // we have in the current module so that we can then call out to that.
2885  llvm::Function *targetFuncs[Target::NUM_ISAS];
2886 
2887  // New helper function checks to see if we need to rewrite the
2888  // type for the dispatch function in case of pointers to varyings
2889  llvm::FunctionType *ftype = lGetVaryingDispatchType(funcs);
2890 
2891  // Now we insert type-punned declarations for dispatched functions.
2892  // This is needed when compiling modules for a set of architectures
2893  // with different vector lengths. Due to restrictions, the return
2894  // type is the same across all architectures, however in different
2895  // modules it may have dissimilar names. The loop below works this
2896  // around.
2897  for (int i = 0; i < Target::NUM_ISAS; ++i) {
2898  if (funcs.func[i])
2899  targetFuncs[i] =
2900  llvm::Function::Create(ftype, llvm::GlobalValue::ExternalLinkage,
2901  funcs.func[i]->getName(), module);
2902  else
2903  targetFuncs[i] = NULL;
2904  }
2905 
2906  bool voidReturn = ftype->getReturnType()->isVoidTy();
2907 
2908  // Now we can emit the definition of the dispatch function..
2909  llvm::Function *dispatchFunc =
2910  llvm::Function::Create(ftype, llvm::GlobalValue::ExternalLinkage,
2911  name.c_str(), module);
2912  llvm::BasicBlock *bblock =
2913  llvm::BasicBlock::Create(*g->ctx, "entry", dispatchFunc);
2914 
2915  // Start by calling out to the function that determines the system's
2916  // ISA and sets __system_best_isa, if it hasn't been set yet.
2917  llvm::CallInst::Create(setISAFunc, "", bblock);
2918 
2919  // Now we can load the system's ISA enumerant
2920  llvm::Value *systemISA =
2921  new llvm::LoadInst(systemBestISAPtr, "system_isa", bblock);
2922 
2923  // Now emit code that works backwards though the available variants of
2924  // the function. We'll call out to the first one we find that will run
2925  // successfully on the system the code is running on. In working
2926  // through the candidate ISAs here backward, we're taking advantage of
2927  // the expectation that they are ordered in the Target::ISA enumerant
2928  // from least to most capable.
2929  for (int i = Target::NUM_ISAS-1; i >= 0; --i) {
2930  if (targetFuncs[i] == NULL)
2931  continue;
2932 
2933  // Emit code to see if the system can run the current candidate
2934  // variant successfully--"is the system's ISA enumerant value >=
2935  // the enumerant value of the current candidate?"
2936 
2937  // dispatchNum is needed to separate generic from *-generic target
2938  int dispatchNum = i;
2939  if ((Target::ISA)(i == Target::GENERIC) &&
2940  !g->target->getTreatGenericAsSmth().empty()) {
2941  if (g->target->getTreatGenericAsSmth() == "knl_generic")
2942  dispatchNum = Target::KNL_AVX512;
2943  else {
2944  Error(SourcePos(), "*-generic target can be called only with knl");
2945  exit(1);
2946  }
2947  }
2948 
2949  llvm::Value *ok =
2950  llvm::CmpInst::Create(llvm::Instruction::ICmp, llvm::CmpInst::ICMP_SGE,
2951  systemISA, LLVMInt32(dispatchNum), "isa_ok", bblock);
2952  llvm::BasicBlock *callBBlock =
2953  llvm::BasicBlock::Create(*g->ctx, "do_call", dispatchFunc);
2954  llvm::BasicBlock *nextBBlock =
2955  llvm::BasicBlock::Create(*g->ctx, "next_try", dispatchFunc);
2956  llvm::BranchInst::Create(callBBlock, nextBBlock, ok, bblock);
2957 
2958  // Emit the code to make the call call in callBBlock.
2959  // Just pass through all of the args from the dispatch function to
2960  // the target-specific function.
2961  std::vector<llvm::Value *> args;
2962  llvm::Function::arg_iterator argIter = dispatchFunc->arg_begin();
2963  llvm::Function::arg_iterator targsIter = targetFuncs[i]->arg_begin();
2964  for (; argIter != dispatchFunc->arg_end(); ++argIter, ++targsIter) {
2965  // Check to see if we rewrote any types in the dispatch function.
2966  // If so, create bitcasts for the appropriate pointer types.
2967  if (argIter->getType() == targsIter->getType()) {
2968  args.push_back(&*argIter);
2969  }
2970  else {
2971  llvm::CastInst *argCast =
2972  llvm::CastInst::CreatePointerCast(&*argIter, targsIter->getType(),
2973  "dpatch_arg_bitcast", callBBlock);
2974  args.push_back(argCast);
2975  }
2976  }
2977  if (voidReturn) {
2978  llvm::CallInst::Create(targetFuncs[i], args, "", callBBlock);
2979  llvm::ReturnInst::Create(*g->ctx, callBBlock);
2980  }
2981  else {
2982  llvm::Value *retValue =
2983  llvm::CallInst::Create(targetFuncs[i], args, "ret_value",
2984  callBBlock);
2985  llvm::ReturnInst::Create(*g->ctx, retValue, callBBlock);
2986  }
2987 
2988  // Otherwise we'll go on to the next candidate and see about that
2989  // one...
2990  bblock = nextBBlock;
2991  }
2992 
2993  // We couldn't find a match that the current system was capable of
2994  // running. We'll call abort(); this is a bit of a blunt hammer--it
2995  // might be preferable to call a user-supplied callback--ISPCError(...)
2996  // or some such, but we don't want to start imposing too much of a
2997  // runtime library requirement either...
2998  llvm::Function *abortFunc = module->getFunction("abort");
2999  Assert(abortFunc);
3000  llvm::CallInst::Create(abortFunc, "", bblock);
3001 
3002  // Return an undef value from the function here; we won't get to this
3003  // point at runtime, but LLVM needs all of the basic blocks to be
3004  // terminated...
3005  if (voidReturn)
3006  llvm::ReturnInst::Create(*g->ctx, bblock);
3007  else {
3008  llvm::Value *undefRet = llvm::UndefValue::get(ftype->getReturnType());
3009  llvm::ReturnInst::Create(*g->ctx, undefRet, bblock);
3010  }
3011 }
3012 
3013 // Initialize a dispatch module
3014 static llvm::Module *lInitDispatchModule() {
3015  llvm::Module *module = new llvm::Module("dispatch_module", *g->ctx);
3016 
3017  module->setTargetTriple(g->target->GetTripleString());
3018 
3019  // DataLayout information supposed to be managed in single place in Target class.
3020  module->setDataLayout(g->target->getDataLayout()->getStringRepresentation());
3021 
3022  // First, link in the definitions from the builtins-dispatch.ll file.
3023  extern unsigned char builtins_bitcode_dispatch[];
3024  extern int builtins_bitcode_dispatch_length;
3025  AddBitcodeToModule(builtins_bitcode_dispatch,
3026  builtins_bitcode_dispatch_length, module);
3027  return module;
3028 }
3029 
3030 // Complete the creation of a dispatch module.
3031 // Given a map that holds the mapping from each of the 'export'ed functions
3032 // in the ispc program to the target-specific variants of the function,
3033 // create a llvm::Module that has a dispatch function for each exported
3034 // function that checks the system's capabilities and picks the most
3035 // appropriate compiled variant of the function.
3036 static void lEmitDispatchModule(llvm::Module *module,
3037  std::map<std::string, FunctionTargetVariants> &functions) {
3038  // Get pointers to things we need below
3039  llvm::Function *setFunc = module->getFunction("__set_system_isa");
3040  Assert(setFunc != NULL);
3041  llvm::Value *systemBestISAPtr =
3042  module->getGlobalVariable("__system_best_isa", true);
3043  Assert(systemBestISAPtr != NULL);
3044 
3045  // For each exported function, create the dispatch function
3046  std::map<std::string, FunctionTargetVariants>::iterator iter;
3047  for (iter = functions.begin(); iter != functions.end(); ++iter)
3048  lCreateDispatchFunction(module, setFunc, systemBestISAPtr,
3049  iter->first, iter->second);
3050 
3051  // Do some rudimentary cleanup of the final result and make sure that
3052  // the module is all ok.
3053 #if ISPC_LLVM_VERSION <= ISPC_LLVM_3_6
3054  llvm::PassManager optPM;
3055 #else // LLVM 3.7+
3056  llvm::legacy::PassManager optPM;
3057 #endif
3058  optPM.add(llvm::createGlobalDCEPass());
3059  optPM.add(llvm::createVerifierPass());
3060  optPM.run(*module);
3061 }
3062 
3063 // Determines if two types are compatible
3064 static bool lCompatibleTypes(llvm::Type *Ty1, llvm::Type *Ty2) {
3065  while (Ty1->getTypeID() == Ty2->getTypeID())
3066  switch (Ty1->getTypeID()) {
3067  case llvm::ArrayType::ArrayTyID:
3068  if (Ty1->getArrayNumElements() !=
3069  Ty2->getArrayNumElements())
3070  return false;
3071  Ty1 = Ty1->getArrayElementType();
3072  Ty2 = Ty2->getArrayElementType();
3073  break;
3074 
3075  case llvm::ArrayType::PointerTyID:
3076  Ty1 = Ty1->getPointerElementType();
3077  Ty2 = Ty2->getPointerElementType();
3078  break;
3079 
3080  case llvm::ArrayType::StructTyID:
3081  return llvm::dyn_cast<llvm::StructType>(Ty1)->isLayoutIdentical(llvm::dyn_cast<llvm::StructType>(Ty2));
3082 
3083  default:
3084  // Pointers for compatible simple types are assumed equal
3085  return Ty1 == Ty2;
3086  }
3087  return false;
3088 }
3089 
3090 // Grab all of the global value definitions from the module and change them
3091 // to be declarations; we'll emit a single definition of each global in the
3092 // final module used with the dispatch functions, so that we don't have
3093 // multiple definitions of them, one in each of the target-specific output
3094 // files.
3095 static void
3096 lExtractOrCheckGlobals(llvm::Module *msrc, llvm::Module *mdst, bool check) {
3097  llvm::Module::global_iterator iter;
3098 
3099  for (iter = msrc->global_begin(); iter != msrc->global_end(); ++iter) {
3100  llvm::GlobalVariable *gv = &*iter;
3101  // Is it a global definition?
3102  if (gv->getLinkage() == llvm::GlobalValue::ExternalLinkage &&
3103  gv->hasInitializer()) {
3104  // Turn this into an 'extern' declaration by clearing its
3105  // initializer.
3106  llvm::Constant *init = gv->getInitializer();
3107  gv->setInitializer(NULL);
3108 
3109  llvm::Type *type = gv->getType()->getElementType();
3110  Symbol *sym =
3111  m->symbolTable->LookupVariable(gv->getName().str().c_str());
3112  Assert(sym != NULL);
3113 
3114  // Check presence and compatibility for the current global
3115  if (check) {
3116  llvm::GlobalVariable *exist =
3117  mdst->getGlobalVariable(gv->getName());
3118  Assert(exist != NULL);
3119 
3120  // It is possible that the types may not match: for
3121  // example, this happens with varying globals if we
3122  // compile to different vector widths
3123  if (!lCompatibleTypes(exist->getType(), gv->getType())) {
3124  Warning(sym->pos, "Mismatch in size/layout of global "
3125  "variable \"%s\" with different targets. "
3126  "Globals must not include \"varying\" types or arrays "
3127  "with size based on programCount when compiling to "
3128  "targets with differing vector widths.",
3129  gv->getName().str().c_str());
3130  }
3131  }
3132  // Alternatively, create it anew and make it match the original
3133  else {
3134  llvm::GlobalVariable *newGlobal =
3135  new llvm::GlobalVariable(*mdst, type, gv->isConstant(),
3136  llvm::GlobalValue::ExternalLinkage,
3137  init, gv->getName());
3138  newGlobal->copyAttributesFrom(gv);
3139  }
3140  }
3141  }
3142 }
3143 
3144 #ifdef ISPC_NVPTX_ENABLED
3145 static std::string lCBEMangle(const std::string &S)
3146 {
3147  std::string Result;
3148 
3149  for (unsigned i = 0, e = S.size(); i != e; ++i) {
3150  if (i+1 != e && ((S[i] == '>' && S[i+1] == '>') ||
3151  (S[i] == '<' && S[i+1] == '<'))) {
3152  Result += '_';
3153  Result += 'A'+(S[i]&15);
3154  Result += 'A'+((S[i]>>4)&15);
3155  Result += '_';
3156  i++;
3157  } else if (isalnum(S[i]) || S[i] == '_' || S[i] == '<' || S[i] == '>') {
3158  Result += S[i];
3159  } else {
3160  Result += '_';
3161  Result += 'A'+(S[i]&15);
3162  Result += 'A'+((S[i]>>4)&15);
3163  Result += '_';
3164  }
3165  }
3166  return Result;
3167 }
3168 #endif /* ISPC_NVPTX_ENABLED */
3169 
3170 int
3171 Module::CompileAndOutput(const char *srcFile,
3172  const char *arch,
3173  const char *cpu,
3174  const char *target,
3175  OutputFlags outputFlags,
3176  OutputType outputType,
3177  const char *outFileName,
3178  const char *headerFileName,
3179  const char *includeFileName,
3180  const char *depsFileName,
3181  const char *depsTargetName,
3182  const char *hostStubFileName,
3183  const char *devStubFileName)
3184 {
3185  if (target == NULL || strchr(target, ',') == NULL) {
3186  // We're only compiling to a single target
3187  g->target = new Target(arch, cpu, target, 0 != (outputFlags & GeneratePIC), g->printTarget);
3188  if (!g->target->isValid())
3189  return 1;
3190 
3191  m = new Module(srcFile);
3192  if (m->CompileFile() == 0) {
3193 #ifdef ISPC_NVPTX_ENABLED
3194  /* NVPTX:
3195  * for PTX target replace '.' with '_' in all global variables
3196  * a PTX identifier name must match [a-zA-Z$_][a-zA-Z$_0-9]*
3197  */
3198  if (g->target->getISA() == Target::NVPTX)
3199  {
3200  /* mangle global variables names */
3201  {
3202  llvm::Module::global_iterator I = m->module->global_begin(), E = m->module->global_end();
3203  for (; I != E; I++)
3204  I->setName(lCBEMangle(I->getName()));
3205  }
3206 
3207  /* mangle functions names */
3208  {
3209  llvm::Module::iterator I = m->module->begin(), E = m->module->end();
3210  for (; I != E; I++)
3211  {
3212  std::string str = I->getName();
3213  if (str.find("operator") != std::string::npos)
3214  I->setName(lCBEMangle(str));
3215  }
3216  }
3217  }
3218 #endif /* ISPC_NVPTX_ENABLED */
3219  if (outputType == CXX) {
3220  if (target == NULL || (strncmp(target, "generic-", 8) != 0
3221  && strstr(target, "-generic-") == NULL)) {
3222  Error(SourcePos(), "When generating C++ output, one of the \"generic-*\" "
3223  "targets must be used.");
3224  return 1;
3225  }
3226  }
3227  else if (outputType == Asm || outputType == Object) {
3228  if (target != NULL &&
3229  (strncmp(target, "generic-", 8) == 0 || strstr(target, "-generic-") != NULL)) {
3230  Error(SourcePos(), "When using a \"generic-*\" compilation target, "
3231  "%s output can not be used.",
3232  (outputType == Asm) ? "assembly" : "object file");
3233  return 1;
3234  }
3235  }
3236 
3237  if (outFileName != NULL)
3238  if (!m->writeOutput(outputType, outputFlags, outFileName, includeFileName))
3239  return 1;
3240  if (headerFileName != NULL)
3241  if (!m->writeOutput(Module::Header, outputFlags, headerFileName))
3242  return 1;
3243  if (depsFileName != NULL || (outputFlags & Module::OutputDepsToStdout)) {
3244  std::string targetName;
3245  if (depsTargetName)
3246  targetName = depsTargetName;
3247  else if (outFileName)
3248  targetName = outFileName;
3249  else if (srcFile) {
3250  targetName = srcFile;
3251  size_t dot = targetName.find_last_of('.');
3252  if (dot != std::string::npos)
3253  targetName.erase(dot, std::string::npos);
3254  targetName.append(".o");
3255  } else
3256  targetName = "a.out";
3257  if (!m->writeOutput(Module::Deps,outputFlags,depsFileName,targetName.c_str(),srcFile))
3258  return 1;
3259  }
3260  if (hostStubFileName != NULL)
3261  if (!m->writeOutput(Module::HostStub,outputFlags,hostStubFileName))
3262  return 1;
3263  if (devStubFileName != NULL)
3264  if (!m->writeOutput(Module::DevStub,outputFlags,devStubFileName))
3265  return 1;
3266  }
3267  else
3268  ++m->errorCount;
3269 
3270  int errorCount = m->errorCount;
3271  delete m;
3272  m = NULL;
3273 
3274  delete g->target;
3275  g->target = NULL;
3276 
3277  return errorCount > 0;
3278  }
3279  else {
3280  if (outputType == CXX) {
3281  Error(SourcePos(), "Illegal to specify more than one target when "
3282  "compiling C++ output.");
3283  return 1;
3284  }
3285  if (srcFile == NULL || !strcmp(srcFile, "-")) {
3286  Error(SourcePos(), "Compiling programs from standard input isn't "
3287  "supported when compiling for multiple targets. Please use "
3288  "an intermediate temporary file.");
3289  return 1;
3290  }
3291  if (cpu != NULL) {
3292  Error(SourcePos(), "Illegal to specify cpu type when compiling "
3293  "for multiple targets.");
3294  return 1;
3295  }
3296 
3297  // The user supplied multiple targets
3298  std::vector<std::string> targets = lExtractTargets(target);
3299  Assert(targets.size() > 1);
3300 
3301  if (outFileName != NULL && strcmp(outFileName, "-") == 0) {
3302  Error(SourcePos(), "Multi-target compilation can't generate output "
3303  "to stdout. Please provide an output filename.\n");
3304  return 1;
3305  }
3306 
3307  // Make sure that the function names for 'export'ed functions have
3308  // the target ISA appended to them.
3309  g->mangleFunctionsWithTarget = true;
3310 
3311  llvm::TargetMachine *targetMachines[Target::NUM_ISAS];
3312  for (int i = 0; i < Target::NUM_ISAS; ++i)
3313  targetMachines[i] = NULL;
3314 
3315  llvm::Module *dispatchModule = NULL;
3316 
3317  std::map<std::string, FunctionTargetVariants> exportedFunctions;
3318  int errorCount = 0;
3319 
3320  // Handle creating a "generic" header file for multiple targets
3321  // that use exported varyings
3322  DispatchHeaderInfo DHI;
3323  if ((targets.size() > 1) && (headerFileName != NULL)) {
3324  DHI.file = fopen(headerFileName, "w");
3325  if (!DHI.file) {
3326  perror("fopen");
3327  return false;
3328  }
3329  DHI.fn = headerFileName;
3330  DHI.EmitUnifs = true;
3331  DHI.EmitFuncs = true;
3332  DHI.EmitFrontMatter = true;
3333  DHI.Emit4 = true;
3334  DHI.Emit8 = true;
3335  DHI.Emit16 = true;
3336  // This is toggled later.
3337  DHI.EmitBackMatter = false;
3338  }
3339 
3340  // Variable is needed later for approptiate dispatch function.
3341  // It indicates if we have *-generic target.
3342  std::string treatGenericAsSmth = "";
3343 
3344  for (unsigned int i = 0; i < targets.size(); ++i) {
3345  g->target = new Target(arch, cpu, targets[i].c_str(), 0 != (outputFlags & GeneratePIC), g->printTarget);
3346  if (!g->target->isValid())
3347  return 1;
3348 
3349  if (!g->target->getTreatGenericAsSmth().empty())
3350  treatGenericAsSmth = g->target->getTreatGenericAsSmth();
3351 
3352  // Issue an error if we've already compiled to a variant of
3353  // this target ISA. (It doesn't make sense to compile to both
3354  // avx and avx-x2, for example.)
3355  if (targetMachines[g->target->getISA()] != NULL) {
3356  Error(SourcePos(), "Can't compile to multiple variants of %s "
3357  "target!\n", g->target->GetISAString());
3358  return 1;
3359  }
3360  targetMachines[g->target->getISA()] = g->target->GetTargetMachine();
3361 
3362  m = new Module(srcFile);
3363  if (m->CompileFile() == 0) {
3364  // Create the dispatch module, unless already created;
3365  // in the latter case, just do the checking
3366  bool check = (dispatchModule != NULL);
3367  if (!check)
3368  dispatchModule = lInitDispatchModule();
3369  lExtractOrCheckGlobals(m->module, dispatchModule, check);
3370 
3371  // Grab pointers to the exported functions from the module we
3372  // just compiled, for use in generating the dispatch function
3373  // later.
3374  lGetExportedFunctions(m->symbolTable, exportedFunctions);
3375 
3376  if (outFileName != NULL) {
3377  std::string targetOutFileName;
3378  // We always generate cpp file for *-generic target during multitarget compilation
3379  if (g->target->getISA() == Target::GENERIC &&
3380  !g->target->getTreatGenericAsSmth().empty()) {
3381  targetOutFileName = lGetTargetFileName(outFileName,
3382  g->target->getTreatGenericAsSmth().c_str(), true);
3383  if (!m->writeOutput(CXX, outputFlags, targetOutFileName.c_str(), includeFileName))
3384  return 1;
3385  }
3386  else {
3387  const char *isaName = g->target->GetISAString();
3388  targetOutFileName = lGetTargetFileName(outFileName, isaName, false);
3389  if (!m->writeOutput(outputType, outputFlags, targetOutFileName.c_str()))
3390  return 1;
3391  }
3392  }
3393  } else {
3394  ++m->errorCount;
3395  }
3396 
3397  errorCount += m->errorCount;
3398  if (errorCount != 0) {
3399  return 1;
3400  }
3401 
3402  // Only write the generate header file, if desired, the first
3403  // time through the loop here.
3404  if (headerFileName != NULL) {
3405  if (i == targets.size()-1) {
3406  // only print backmatter on the last target.
3407  DHI.EmitBackMatter = true;
3408  }
3409 
3410  const char *isaName;
3411  if (g->target->getISA() == Target::GENERIC &&
3412  !g->target->getTreatGenericAsSmth().empty())
3413  isaName = g->target->getTreatGenericAsSmth().c_str();
3414  else
3415  isaName = g->target->GetISAString();
3416  std::string targetHeaderFileName =
3417  lGetTargetFileName(headerFileName, isaName, false);
3418  // write out a header w/o target name for the first target only
3419  if (!m->writeOutput(Module::Header, outputFlags, headerFileName, "", nullptr, &DHI)) {
3420  return 1;
3421  }
3422  if (!m->writeOutput(Module::Header, outputFlags, targetHeaderFileName.c_str())) {
3423  return 1;
3424  }
3425  if (i == targets.size()-1) {
3426  fclose(DHI.file);
3427  }
3428  }
3429 
3430  delete g->target;
3431  g->target = NULL;
3432 
3433  // Important: Don't delete the llvm::Module *m here; we need to
3434  // keep it around so the llvm::Functions *s stay valid for when
3435  // we generate the dispatch module's functions...
3436  }
3437 
3438  // Find the first non-NULL target machine from the targets we
3439  // compiled to above. We'll use this as the target machine for
3440  // compiling the dispatch module--this is safe in that it is the
3441  // least-common-denominator of all of the targets we compiled to.
3442  llvm::TargetMachine *firstTargetMachine = NULL;
3443  int i = 0;
3444  const char *firstISA;
3445  while (i < Target::NUM_ISAS && firstTargetMachine == NULL) {
3446  firstISA = Target::ISAToTargetString((Target::ISA) i);
3447  firstTargetMachine = targetMachines[i++];
3448  }
3449  Assert(firstTargetMachine != NULL);
3450 
3451  g->target = new Target(arch, cpu, firstISA, 0 != (outputFlags & GeneratePIC), false, treatGenericAsSmth);
3452  if (!g->target->isValid()) {
3453  return 1;
3454  }
3455 
3456  lEmitDispatchModule(dispatchModule, exportedFunctions);
3457 
3458  if (outFileName != NULL) {
3459  if (outputType == Bitcode)
3460  writeBitcode(dispatchModule, outFileName);
3461  else
3462  writeObjectFileOrAssembly(firstTargetMachine, dispatchModule,
3463  outputType, outFileName);
3464  }
3465 
3466  if (depsFileName != NULL)
3467  if (!m->writeOutput(Module::Deps, outputFlags, depsFileName))
3468  return 1;
3469 
3470  delete g->target;
3471  g->target = NULL;
3472 
3473 
3474  return errorCount > 0;
3475  }
3476 }
int yyparse()
bool IsVoidType() const
Definition: type.cpp:251
llvm::Value * storagePtr
Definition: sym.h:72
static const AtomicType * VaryingInt32
Definition: type.h:349
bool writeOutput(OutputType ot, OutputFlags flags, const char *filename, const char *includeFileName=NULL, const char *sourceFileName=NULL, DispatchHeaderInfo *DHI=0)
Definition: module.cpp:1228
bool IsVaryingType() const
Definition: type.h:150
Expr * GetParameterDefault(int i) const
Definition: type.cpp:3410
const std::string GetReturnTypeString() const
Definition: type.cpp:3310
llvm::Function * function
Definition: sym.h:76
const VectorType * GetAsNonConstType() const
Definition: type.cpp:1818
int GetElementCount() const
Definition: type.cpp:1531
static void lPrintFunctionDeclarations(FILE *file, const std::vector< Symbol * > &funcs, bool useExternC=1, bool rewriteForDispatch=false)
Definition: module.cpp:1918
llvm::TargetMachine * GetTargetMachine() const
Definition: ispc.h:233
Definition: ast.h:144
Opt opt
Definition: ispc.h:548
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:1642
std::vector< std::pair< const Type *, SourcePos > > exportedTypes
Definition: module.h:181
bool writeDevStub(const char *filename)
Definition: module.cpp:2061
Declaration of the FunctionEmitContext class
const std::string GetCStructName() const
Definition: type.cpp:2096
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:1626
static llvm::Module * lInitDispatchModule()
Definition: module.cpp:3014
static void lCreateDispatchFunction(llvm::Module *module, llvm::Function *setISAFunc, llvm::Value *systemBestISAPtr, const std::string &name, FunctionTargetVariants &funcs)
Definition: module.cpp:2878
#define UNESCAPE_SEQ(c, esc)
bool IsArrayType() const
Definition: type.cpp:241
static void lExtractOrCheckGlobals(llvm::Module *msrc, llvm::Module *mdst, bool check)
Definition: module.cpp:3096
static void lEmitEnumDecls(const std::vector< const EnumType * > &enumTypes, FILE *file)
Definition: module.cpp:1750
int getVectorWidth() const
Definition: ispc.h:286
static bool lSymbolIsExported(const Symbol *s)
Definition: module.cpp:2777
Module * m
Definition: ispc.cpp:101
static int CompileAndOutput(const char *srcFile, const char *arch, const char *cpu, const char *targets, OutputFlags outputFlags, OutputType outputType, const char *outFileName, const char *headerFileName, const char *includeFileName, const char *depsFileName, const char *depsTargetName, const char *hostStubFileName, const char *devStubFileName)
Definition: module.cpp:3171
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:2024
int first_line
Definition: ispc.h:142
Structure that defines a compilation target.
Definition: ispc.h:184
Target * target
Definition: ispc.h:550
void AddBitcodeToModule(const unsigned char *bitcode, int length, llvm::Module *module, SymbolTable *symbolTable=NULL, bool warn=true)
Definition: builtins.cpp:846
bool AddVariable(Symbol *symbol)
Definition: sym.cpp:98
Expression representing a compile-time constant value.
Definition: expr.h:390
llvm::Function * func[Target::NUM_ISAS]
Definition: module.cpp:2794
Abstract base class for types that represent sequences.
Definition: type.h:531
std::vector< std::string > includePath
Definition: ispc.h:651
static void lEmitStructDecls(std::vector< const StructType * > &structTypes, FILE *file, bool emitUnifs=true)
Definition: module.cpp:1726
static void lCheckExportedParameterTypes(const Type *type, const std::string &name, SourcePos pos)
Definition: module.cpp:864
bool NoOmitFramePointer
Definition: ispc.h:573
#define Assert(expr)
Definition: ispc.h:173
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:3336
bool IsPointerType() const
Definition: type.cpp:235
void yy_switch_to_buffer(YY_BUFFER_STATE)
static void lEmitVectorTypedefs(const std::vector< const VectorType * > &types, FILE *file)
Definition: module.cpp:1790
Declarations related to optimization passes.
void DefineStdlib(SymbolTable *symbolTable, llvm::LLVMContext *ctx, llvm::Module *module, bool includeStdlib)
Definition: builtins.cpp:1225
const Type * GetElementType(const std::string &name) const
Definition: type.cpp:2501
bool forceAlignedMemory
Definition: ispc.h:472
virtual llvm::Constant * GetConstant(const Type *type) const
Definition: expr.cpp:102
const FunctionType * FTs[Target::NUM_ISAS]
Definition: module.cpp:2795
Declarations of functions related to builtins and the standard library.
const char * fn
Definition: module.cpp:2430
const char * GetISAString() const
Definition: ispc.cpp:1332
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:1955
virtual std::string GetString() const =0
bool writeHeader(const char *filename)
Definition: module.cpp:2321
const Type * GetReferenceTarget() const
Definition: type.cpp:2800
int GetSOAWidth() const
Definition: type.h:160
ConstExpr * constValue
Definition: sym.h:87
bool hasRand() const
Definition: ispc.h:296
static const StructType * lGetElementStructType(const Type *t)
Definition: module.cpp:1611
bool writeObjectFileOrAssembly(OutputType outputType, const char *filename)
Definition: module.cpp:1508
void GetDirectoryAndFileName(const std::string &currentDir, const std::string &relativeName, std::string *directory, std::string *filename)
Definition: util.cpp:565
header file with declarations for symbol and symbol table classes.
bool writeHostStub(const char *filename)
Definition: module.cpp:2199
Type representing a reference to another (non-reference) type.
Definition: type.h:834
static llvm::FunctionType * lGetVaryingDispatchType(FunctionTargetVariants &funcs)
Definition: module.cpp:2815
bool includeStdlib
Definition: ispc.h:559
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:438
llvm::ConstantInt * LLVMInt32(int32_t i)
Definition: llvmutil.cpp:263
static bool lIsExported(const Symbol *sym)
Definition: module.cpp:1947
llvm::Module * module
Definition: module.h:166
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:1461
Globals * g
Definition: ispc.cpp:100
bool IsUniformType() const
Definition: type.h:145
bool debugPrint
Definition: ispc.h:567
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:1436
bool LookupFunction(const char *name, std::vector< Symbol * > *matches=NULL)
Definition: sym.cpp:162
const std::string & GetParameterName(int i) const
Definition: type.cpp:3424
void RegisterDependency(const std::string &fileName)
Definition: module.cpp:143
static bool lContainsPtrToVarying(const StructType *st)
Definition: module.cpp:1624
const bool isExternC
Definition: type.h:953
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:294
void AddFunctionDeclaration(const std::string &name, const FunctionType *ftype, StorageClass sc, bool isInline, SourcePos pos)
Definition: module.cpp:924
llvm::Type * LLVMType(llvm::LLVMContext *ctx) const
Definition: type.cpp:1863
bool printTarget
Definition: ispc.h:570
int GetValues(bool *, bool forceVarying=false) const
Definition: expr.cpp:5873
virtual std::string GetCDeclaration(const std::string &name) const =0
bool runCPP
Definition: ispc.h:563
static void lDeclareSizeAndPtrIntTypes(SymbolTable *symbolTable)
Definition: module.cpp:150
Representation of a structure holding a number of members.
Definition: type.h:692
virtual llvm::DIType GetDIType(llvm::DIDescriptor scope) const =0
char currentDirectory[1024]
Definition: ispc.h:643
std::string Mangle() const
Definition: type.cpp:3162
bool mangleFunctionsWithTarget
Definition: ispc.h:628
Header file with declarations for various LLVM utility stuff.
int CompileFile()
Definition: module.cpp:489
const Type * GetParameterType(int i) const
Definition: type.cpp:3403
ISA getISA() const
Definition: ispc.h:270
bool emitInstrumentation
Definition: ispc.h:610
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:742
static void lGetExportedFunctions(SymbolTable *symbolTable, std::map< std::string, FunctionTargetVariants > &functions)
Definition: module.cpp:2803
StorageClass storageClass
Definition: sym.h:96
Representation of a range of positions in a source file.
Definition: ispc.h:137
int GetElementCount() const
Definition: type.cpp:1851
bool generateDebuggingSymbols
Definition: ispc.h:614
Type implementation for enumerated types.
Definition: type.h:370
std::string GetCDeclarationForDispatch(const std::string &fname) const
Definition: type.cpp:3209
StorageClass
Definition: ispc.h:121
bool force32BitAddressing
Definition: ispc.h:458
bool dllExport
Definition: ispc.h:658
const char * name
Definition: ispc.h:141
void markFuncWithTargetAttr(llvm::Function *func)
Definition: ispc.cpp:1502
void execPreprocessor(const char *infilename, llvm::raw_string_ostream *ostream) const
Definition: module.cpp:2554
SourcePos pos
Definition: ast.h:77
static std::vector< std::string > lExtractTargets(const char *target)
Definition: module.cpp:2759
void Warning(SourcePos p, const char *format,...) PRINTF_FUNC
Definition: util.cpp:410
static const AtomicType * VaryingInt64
Definition: type.h:354
static void lAddTypeIfNew(const Type *type, std::vector< const T * > *exportedTypes)
Definition: module.cpp:1830
const Type * GetReturnType() const
Definition: type.h:926
#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:1766
YY_BUFFER_STATE yy_scan_string(const char *)
std::string getTreatGenericAsSmth() const
Definition: ispc.h:272
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:1899
static void lEmitDispatchModule(llvm::Module *module, std::map< std::string, FunctionTargetVariants > &functions)
Definition: module.cpp:3036
static bool Equal(const Type *a, const Type *b)
Definition: type.cpp:3752
ISA
Definition: ispc.h:192
const bool isTask
Definition: type.h:945
llvm::DIFile GetDIFile() const
Definition: ispc.cpp:1602
void AddFunctionDefinition(const std::string &name, const FunctionType *ftype, Stmt *code)
Definition: module.cpp:1190
OutputFlags
Definition: module.h:109
static std::string lGetTargetFileName(const char *outFileName, const char *isaString, bool forceCXX)
Definition: module.cpp:2722
static void lUnescapeStringInPlace(std::string &str)
Definition: module.cpp:1963
Type representing a function (return type + argument types)
Definition: type.h:885
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:3064
std::string GetCDeclaration(const std::string &fname) const
Definition: type.cpp:3178
Expr * TypeConvertExpr(Expr *expr, const Type *toType, const char *errorMsgBase)
Definition: expr.cpp:602
bool IsReferenceType() const
Definition: type.cpp:246
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:2334
bool writeDeps(const char *filename, bool generateMakeRule, const char *targetName=NULL, const char *srcFilename=NULL)
Definition: module.cpp:1991
FILE * yyin
static const Type * SizeUnsizedArrays(const Type *type, Expr *initExpr)
Definition: type.cpp:1662
const SourcePos & GetParameterSourcePos(int i) const
Definition: type.cpp:3417
std::vector< std::string > cppArgs
Definition: ispc.h:647
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:268
const bool isExported
Definition: type.h:949
const Type * GetElementType() const
Definition: type.cpp:1537
const llvm::DataLayout * getDataLayout() const
Definition: ispc.h:265
virtual const Type * GetAsUnsignedType() const
Definition: type.cpp:3441
Declaration of the Module class, which is the ispc-side representation of the results of compiling a ...
int errorCount
Definition: module.h:159
llvm::LLVMContext * ctx
Definition: ispc.h:639
const char * filename
Definition: module.h:178
void yy_delete_buffer(YY_BUFFER_STATE)
const Type * type
Definition: sym.h:84
llvm::DIBuilder * diBuilder
Definition: module.h:169
static void lGetExportedTypes(const Type *type, std::vector< const StructType * > *exportedStructTypes, std::vector< const EnumType * > *exportedEnumTypes, std::vector< const VectorType * > *exportedVectorTypes)
Definition: module.cpp:1850
static bool EqualIgnoringConst(const Type *a, const Type *b)
Definition: type.cpp:3758
virtual const Type * GetReferenceTarget() const
Definition: type.cpp:3434
std::string GetTripleString() const
Definition: ispc.cpp:1255
bool disableAsserts
Definition: ispc.h:462
bool IsSOAType() const
Definition: type.h:156
void Debug(SourcePos p, const char *format,...) PRINTF_FUNC
Definition: util.cpp:398
bool is32Bit() const
Definition: ispc.h:276
static const AtomicType * VaryingUInt32
Definition: type.h:352
int GetNumParameters() const
Definition: type.h:937
static const char * ISAToTargetString(Target::ISA isa)
Definition: ispc.cpp:1341
SymbolTable * symbolTable
Definition: module.h:163
llvm::Function * exportedFunction
Definition: sym.h:79
int GetElementCount() const
Definition: type.h:745
File with declarations for classes related to type representation.
AST * ast
Definition: module.h:179
bool hasTranscendentals() const
Definition: ispc.h:302
bool WriteCXXFile(llvm::Module *module, const char *fn, int vectorWidth, const char *includeName)
Definition: cbackend.cpp:5529
bool writeDispatchHeader(DispatchHeaderInfo *DHI)
Definition: module.cpp:2434
One-dimensional array type.
Definition: type.h:555