Intel® Implicit SPMD Program Compiler (Intel® ISPC)  1.13.0
type.cpp
Go to the documentation of this file.
1 /*
2  Copyright (c) 2010-2020, 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 type.cpp
35  @brief Definitions for classes related to type representation
36 */
37 
38 #include "type.h"
39 #include "expr.h"
40 #include "llvmutil.h"
41 #include "module.h"
42 #include "sym.h"
43 
44 #include <llvm/BinaryFormat/Dwarf.h>
45 #include <llvm/IR/DIBuilder.h>
46 #include <llvm/IR/DebugInfo.h>
47 #include <llvm/IR/Module.h>
48 #include <llvm/IR/Value.h>
49 #include <llvm/Support/MathExtras.h>
50 #include <map>
51 #include <stdio.h>
52 
53 /** Utility routine used in code that prints out declarations; returns true
54  if the given name should be printed, false otherwise. This allows us
55  to omit the names for various internal things (whose names start with
56  double underscores) and emit anonymous declarations for them instead.
57  */
58 
59 static bool lShouldPrintName(const std::string &name) {
60  if (name.size() == 0)
61  return false;
62  else if (name[0] != '_' && name[0] != '$')
63  return true;
64  else
65  return (name.size() == 1) || (name[1] != '_');
66 }
67 
68 /** Utility routine to create a llvm array type of the given number of
69  the given element type. */
70 static llvm::DIType *lCreateDIArray(llvm::DIType *eltType, int count) {
71 
72  llvm::Metadata *sub = m->diBuilder->getOrCreateSubrange(0, count);
73  std::vector<llvm::Metadata *> subs;
74  subs.push_back(sub);
75  llvm::DINodeArray subArray = m->diBuilder->getOrCreateArray(subs);
76  uint64_t size = eltType->getSizeInBits() * count;
77  uint64_t align = eltType->getAlignInBits();
78 
79  return m->diBuilder->createArrayType(size, align, eltType, subArray);
80 }
81 
82 ///////////////////////////////////////////////////////////////////////////
83 // Variability
84 
85 std::string Variability::GetString() const {
86  switch (type) {
87  case Uniform:
88  return "uniform";
89  case Varying:
90  return "varying";
91  case SOA: {
92  char buf[32];
93  snprintf(buf, sizeof(buf), "soa<%d>", soaWidth);
94  return std::string(buf);
95  }
96  case Unbound:
97  return "/*unbound*/";
98  default:
99  FATAL("Unhandled variability");
100  return "";
101  }
102 }
103 
104 std::string Variability::MangleString() const {
105  switch (type) {
106  case Uniform:
107  return "un";
108  case Varying:
109  return "vy";
110  case SOA: {
111  char buf[32];
112  snprintf(buf, sizeof(buf), "soa<%d>", soaWidth);
113  return std::string(buf);
114  }
115  case Unbound:
116  FATAL("Unbound unexpected in Variability::MangleString()");
117  default:
118  FATAL("Unhandled variability");
119  return "";
120  }
121 }
122 
123 ///////////////////////////////////////////////////////////////////////////
124 // Type
125 llvm::Type *Type::LLVMStorageType(llvm::LLVMContext *ctx) const { return LLVMType(ctx); }
126 ///////////////////////////////////////////////////////////////////////////
127 // AtomicType
128 
151 const AtomicType *AtomicType::Void = new AtomicType(TYPE_VOID, Variability::Uniform, false);
152 
154  : Type(ATOMIC_TYPE), basicType(bt), variability(v), isConst(ic) {
155  asOtherConstType = NULL;
156  asUniformType = asVaryingType = NULL;
157 }
158 
160 
161 bool Type::IsPointerType() const { return (CastType<PointerType>(this) != NULL); }
162 
163 bool Type::IsArrayType() const { return (CastType<ArrayType>(this) != NULL); }
164 
165 bool Type::IsReferenceType() const { return (CastType<ReferenceType>(this) != NULL); }
166 
167 bool Type::IsVoidType() const { return EqualIgnoringConst(this, AtomicType::Void); }
168 
170 
171 bool AtomicType::IsIntType() const {
174 }
175 
179 }
180 
181 bool AtomicType::IsBoolType() const { return basicType == TYPE_BOOL; }
182 
183 bool AtomicType::IsConstType() const { return isConst; }
184 
186  if (IsUnsignedType() == true)
187  return this;
188 
189  if (IsIntType() == false)
190  return NULL;
191 
192  switch (basicType) {
193  case TYPE_INT8:
195  case TYPE_INT16:
197  case TYPE_INT32:
199  case TYPE_INT64:
201  default:
202  FATAL("Unexpected basicType in GetAsUnsignedType()");
203  return NULL;
204  }
205 }
206 
208  if (isConst == true)
209  return this;
210 
211  if (asOtherConstType == NULL) {
214  }
215  return asOtherConstType;
216 }
217 
219  if (isConst == false)
220  return this;
221 
222  if (asOtherConstType == NULL) {
225  }
226  return asOtherConstType;
227 }
228 
229 const AtomicType *AtomicType::GetBaseType() const { return this; }
230 
234  return this;
235 
236  if (asVaryingType == NULL) {
240  }
241  return asVaryingType;
242 }
243 
247  return this;
248 
249  if (asUniformType == NULL) {
250  BasicType bType = basicType;
251  // Varying bool needs to be handled differently since LLVMTypes::BoolVectorType
252  // is not always composed of i1.
254  switch (g->target->getMaskBitCount()) {
255  case 1:
256  bType = TYPE_BOOL;
257  break;
258  case 8:
259  bType = TYPE_INT8;
260  break;
261  case 16:
262  bType = TYPE_INT16;
263  break;
264  case 32:
265  bType = TYPE_INT32;
266  break;
267  case 64:
268  bType = TYPE_INT64;
269  break;
270  default:
271  FATAL("Unhandled mask width");
272  }
273  }
277  }
278  return asUniformType;
279 }
280 
284  return this;
286 }
287 
288 const AtomicType *AtomicType::GetAsSOAType(int width) const {
291  return this;
293 }
294 
298  return this;
299  return new AtomicType(basicType, v, isConst);
300 }
301 
302 std::string AtomicType::GetString() const {
303  std::string ret;
304  if (isConst)
305  ret += "const ";
306  if (basicType != TYPE_VOID) {
307  ret += variability.GetString();
308  ret += " ";
309  }
310 
311  switch (basicType) {
312  case TYPE_VOID:
313  ret += "void";
314  break;
315  case TYPE_BOOL:
316  ret += "bool";
317  break;
318  case TYPE_INT8:
319  ret += "int8";
320  break;
321  case TYPE_UINT8:
322  ret += "unsigned int8";
323  break;
324  case TYPE_INT16:
325  ret += "int16";
326  break;
327  case TYPE_UINT16:
328  ret += "unsigned int16";
329  break;
330  case TYPE_INT32:
331  ret += "int32";
332  break;
333  case TYPE_UINT32:
334  ret += "unsigned int32";
335  break;
336  case TYPE_FLOAT:
337  ret += "float";
338  break;
339  case TYPE_INT64:
340  ret += "int64";
341  break;
342  case TYPE_UINT64:
343  ret += "unsigned int64";
344  break;
345  case TYPE_DOUBLE:
346  ret += "double";
347  break;
348  default:
349  FATAL("Logic error in AtomicType::GetString()");
350  }
351  return ret;
352 }
353 
354 std::string AtomicType::Mangle() const {
355  std::string ret;
356  if (isConst)
357  ret += "C";
358  ret += variability.MangleString();
359 
360  switch (basicType) {
361  case TYPE_VOID:
362  ret += "v";
363  break;
364  case TYPE_BOOL:
365  ret += "b";
366  break;
367  case TYPE_INT8:
368  ret += "t";
369  break;
370  case TYPE_UINT8:
371  ret += "T";
372  break;
373  case TYPE_INT16:
374  ret += "s";
375  break;
376  case TYPE_UINT16:
377  ret += "S";
378  break;
379  case TYPE_INT32:
380  ret += "i";
381  break;
382  case TYPE_UINT32:
383  ret += "u";
384  break;
385  case TYPE_FLOAT:
386  ret += "f";
387  break;
388  case TYPE_INT64:
389  ret += "I";
390  break;
391  case TYPE_UINT64:
392  ret += "U";
393  break;
394  case TYPE_DOUBLE:
395  ret += "d";
396  break;
397  default:
398  FATAL("Logic error in AtomicType::Mangle()");
399  }
400  return ret;
401 }
402 
403 std::string AtomicType::GetCDeclaration(const std::string &name) const {
404  std::string ret;
406  Assert(m->errorCount > 0);
407  return ret;
408  }
409  if (isConst)
410  ret += "const ";
411 
412  switch (basicType) {
413  case TYPE_VOID:
414  ret += "void";
415  break;
416  case TYPE_BOOL:
417  ret += "bool";
418  break;
419  case TYPE_INT8:
420  ret += "int8_t";
421  break;
422  case TYPE_UINT8:
423  ret += "uint8_t";
424  break;
425  case TYPE_INT16:
426  ret += "int16_t";
427  break;
428  case TYPE_UINT16:
429  ret += "uint16_t";
430  break;
431  case TYPE_INT32:
432  ret += "int32_t";
433  break;
434  case TYPE_UINT32:
435  ret += "uint32_t";
436  break;
437  case TYPE_FLOAT:
438  ret += "float";
439  break;
440  case TYPE_INT64:
441  ret += "int64_t";
442  break;
443  case TYPE_UINT64:
444  ret += "uint64_t";
445  break;
446  case TYPE_DOUBLE:
447  ret += "double";
448  break;
449  default:
450  FATAL("Logic error in AtomicType::GetCDeclaration()");
451  }
452 
453  if (lShouldPrintName(name)) {
454  ret += " ";
455  ret += name;
456  }
457 
458  if (variability == Variability::SOA) {
459  char buf[32];
460  snprintf(buf, sizeof(buf), "[%d]", variability.soaWidth);
461  ret += buf;
462  }
463 
464  return ret;
465 }
466 
467 static llvm::Type *lGetAtomicLLVMType(llvm::LLVMContext *ctx, const AtomicType *aType, bool isStorageType) {
470  Assert(variability.type != Variability::Unbound);
471  bool isUniform = (variability == Variability::Uniform);
472  bool isVarying = (variability == Variability::Varying);
473 
474  if (isUniform || isVarying) {
475  switch (basicType) {
477  return llvm::Type::getVoidTy(*ctx);
479  if (isStorageType)
481  else
482  return isUniform ? LLVMTypes::BoolType : LLVMTypes::BoolVectorType;
485  return isUniform ? LLVMTypes::Int8Type : LLVMTypes::Int8VectorType;
499  default:
500  FATAL("logic error in lGetAtomicLLVMType");
501  return NULL;
502  }
503  } else {
504  ArrayType at(aType->GetAsUniformType(), variability.soaWidth);
505  return at.LLVMType(ctx);
506  }
507 }
508 
509 llvm::Type *AtomicType::LLVMStorageType(llvm::LLVMContext *ctx) const { return lGetAtomicLLVMType(ctx, this, true); }
510 llvm::Type *AtomicType::LLVMType(llvm::LLVMContext *ctx) const { return lGetAtomicLLVMType(ctx, this, false); }
511 
512 llvm::DIType *AtomicType::GetDIType(llvm::DIScope *scope) const {
514 
516  switch (basicType) {
517  case TYPE_VOID:
518  return NULL;
519 
520  case TYPE_BOOL:
521  return m->diBuilder->createBasicType("bool", 32 /* size */, llvm::dwarf::DW_ATE_unsigned);
522  break;
523  case TYPE_INT8:
524  return m->diBuilder->createBasicType("int8", 8 /* size */, llvm::dwarf::DW_ATE_signed);
525  break;
526  case TYPE_UINT8:
527  return m->diBuilder->createBasicType("uint8", 8 /* size */, llvm::dwarf::DW_ATE_unsigned);
528  break;
529  case TYPE_INT16:
530  return m->diBuilder->createBasicType("int16", 16 /* size */, llvm::dwarf::DW_ATE_signed);
531  break;
532  case TYPE_UINT16:
533  return m->diBuilder->createBasicType("uint16", 16 /* size */, llvm::dwarf::DW_ATE_unsigned);
534  break;
535  case TYPE_INT32:
536  return m->diBuilder->createBasicType("int32", 32 /* size */, llvm::dwarf::DW_ATE_signed);
537  break;
538  case TYPE_UINT32:
539  return m->diBuilder->createBasicType("uint32", 32 /* size */, llvm::dwarf::DW_ATE_unsigned);
540  break;
541  case TYPE_FLOAT:
542  return m->diBuilder->createBasicType("float", 32 /* size */, llvm::dwarf::DW_ATE_float);
543  break;
544  case TYPE_DOUBLE:
545  return m->diBuilder->createBasicType("double", 64 /* size */, llvm::dwarf::DW_ATE_float);
546  break;
547  case TYPE_INT64:
548  return m->diBuilder->createBasicType("int64", 64 /* size */, llvm::dwarf::DW_ATE_signed);
549  break;
550  case TYPE_UINT64:
551  return m->diBuilder->createBasicType("uint64", 64 /* size */, llvm::dwarf::DW_ATE_unsigned);
552  break;
553 
554  default:
555  FATAL("unhandled basic type in AtomicType::GetDIType()");
556 
557  return NULL;
558  }
559  } else if (variability == Variability::Varying) {
560 
561  llvm::Metadata *sub = m->diBuilder->getOrCreateSubrange(0, g->target->getVectorWidth());
562 
563  llvm::DINodeArray subArray = m->diBuilder->getOrCreateArray(sub);
564  llvm::DIType *unifType = GetAsUniformType()->GetDIType(scope);
565  uint64_t size = unifType->getSizeInBits() * g->target->getVectorWidth();
566  uint64_t align = unifType->getAlignInBits() * g->target->getVectorWidth();
567  return m->diBuilder->createVectorType(size, align, unifType, subArray);
568  } else {
571  return at.GetDIType(scope);
572  }
573 }
574 
575 ///////////////////////////////////////////////////////////////////////////
576 // EnumType
577 
579  // name = "/* (anonymous) */";
580  isConst = false;
582 }
583 
584 EnumType::EnumType(const char *n, SourcePos p) : Type(ENUM_TYPE), pos(p), name(n) {
585  isConst = false;
587 }
588 
590 
591 bool EnumType::IsBoolType() const { return false; }
592 
593 bool EnumType::IsFloatType() const { return false; }
594 
595 bool EnumType::IsIntType() const { return true; }
596 
597 bool EnumType::IsUnsignedType() const { return true; }
598 
599 bool EnumType::IsConstType() const { return isConst; }
600 
601 const EnumType *EnumType::GetBaseType() const { return this; }
602 
604  if (IsUniformType())
605  return this;
606  else {
607  EnumType *enumType = new EnumType(*this);
608  enumType->variability = Variability::Uniform;
609  return enumType;
610  }
611 }
612 
615  return this;
616  else {
617  EnumType *enumType = new EnumType(*this);
618  enumType->variability = v;
619  return enumType;
620  }
621 }
622 
624  if (IsVaryingType())
625  return this;
626  else {
627  EnumType *enumType = new EnumType(*this);
629  return enumType;
630  }
631 }
632 
634  if (HasUnboundVariability())
635  return this;
636  else {
637  EnumType *enumType = new EnumType(*this);
639  return enumType;
640  }
641 }
642 
643 const EnumType *EnumType::GetAsSOAType(int width) const {
644  if (GetSOAWidth() == width)
645  return this;
646  else {
647  EnumType *enumType = new EnumType(*this);
648  enumType->variability = Variability(Variability::SOA, width);
649  return enumType;
650  }
651 }
652 
654  if (isConst)
655  return this;
656  else {
657  EnumType *enumType = new EnumType(*this);
658  enumType->isConst = true;
659  return enumType;
660  }
661 }
662 
664  if (!isConst)
665  return this;
666  else {
667  EnumType *enumType = new EnumType(*this);
668  enumType->isConst = false;
669  return enumType;
670  }
671 }
672 
673 std::string EnumType::GetString() const {
674  std::string ret;
675  if (isConst)
676  ret += "const ";
677  ret += variability.GetString();
678 
679  ret += " enum ";
680  if (name.size())
681  ret += name;
682  return ret;
683 }
684 
685 std::string EnumType::Mangle() const {
687 
688  std::string ret;
689  if (isConst)
690  ret += "C";
691  ret += variability.MangleString();
692  // ret += std::string("enum[") + name + std::string("]");
693  ret += std::string("enum_5B_") + name + std::string("_5D_");
694  return ret;
695 }
696 
697 std::string EnumType::GetCDeclaration(const std::string &varName) const {
699  Assert(m->errorCount > 0);
700  return "";
701  }
702 
703  std::string ret;
704  if (isConst)
705  ret += "const ";
706  ret += "enum";
707  if (name.size())
708  ret += std::string(" ") + name;
709 
710  if (lShouldPrintName(varName)) {
711  ret += " ";
712  ret += varName;
713  }
714 
717  char buf[32];
718  snprintf(buf, sizeof(buf), "[%d]", vWidth);
719  ret += buf;
720  }
721 
722  return ret;
723 }
724 
725 llvm::Type *EnumType::LLVMType(llvm::LLVMContext *ctx) const {
727 
728  switch (variability.type) {
730  return LLVMTypes::Int32Type;
733  case Variability::SOA: {
734  ArrayType at(AtomicType::UniformInt32, variability.soaWidth);
735  return at.LLVMType(ctx);
736  }
737  default:
738  FATAL("Unexpected variability in EnumType::LLVMType()");
739  return NULL;
740  }
741 }
742 
743 llvm::DIType *EnumType::GetDIType(llvm::DIScope *scope) const {
744 
745  std::vector<llvm::Metadata *> enumeratorDescriptors;
746  for (unsigned int i = 0; i < enumerators.size(); ++i) {
747  unsigned int enumeratorValue;
748  Assert(enumerators[i]->constValue != NULL);
749  int count = enumerators[i]->constValue->GetValues(&enumeratorValue);
750  Assert(count == 1);
751 
752  llvm::Metadata *descriptor = m->diBuilder->createEnumerator(enumerators[i]->name, enumeratorValue);
753  enumeratorDescriptors.push_back(descriptor);
754  }
755 
756  llvm::DINodeArray elementArray = m->diBuilder->getOrCreateArray(enumeratorDescriptors);
757  llvm::DIFile *diFile = pos.GetDIFile();
758  llvm::DIType *underlyingType = AtomicType::UniformInt32->GetDIType(scope);
759  llvm::DIType *diType =
760  m->diBuilder->createEnumerationType(diFile, name, diFile, pos.first_line, 32 /* size in bits */,
761  32 /* align in bits */, elementArray, underlyingType, name);
762  switch (variability.type) {
764  return diType;
765  case Variability::Varying: {
766  llvm::Metadata *sub = m->diBuilder->getOrCreateSubrange(0, g->target->getVectorWidth());
767 
768  llvm::DINodeArray subArray = m->diBuilder->getOrCreateArray(sub);
769  // llvm::DebugNodeArray subArray = m->diBuilder->getOrCreateArray(sub);
770  uint64_t size = diType->getSizeInBits() * g->target->getVectorWidth();
771  uint64_t align = diType->getAlignInBits() * g->target->getVectorWidth();
772  return m->diBuilder->createVectorType(size, align, diType, subArray);
773  }
774  case Variability::SOA: {
775  return lCreateDIArray(diType, variability.soaWidth);
776  }
777  default:
778  FATAL("Unexpected variability in EnumType::GetDIType()");
779  return NULL;
780  }
781 }
782 
783 void EnumType::SetEnumerators(const std::vector<Symbol *> &e) { enumerators = e; }
784 
785 int EnumType::GetEnumeratorCount() const { return (int)enumerators.size(); }
786 
787 const Symbol *EnumType::GetEnumerator(int i) const { return enumerators[i]; }
788 
789 ///////////////////////////////////////////////////////////////////////////
790 // PointerType
791 
793 
794 PointerType::PointerType(const Type *t, Variability v, bool ic, bool is, bool fr)
795  : Type(POINTER_TYPE), variability(v), isConst(ic), isSlice(is), isFrozen(fr) {
796  baseType = t;
797 }
798 
800  return new PointerType(t, Variability(Variability::Uniform), false, is);
801 }
802 
804  return new PointerType(t, Variability(Variability::Varying), false);
805 }
806 
809 }
810 
812 
813 bool PointerType::IsBoolType() const { return false; }
814 
815 bool PointerType::IsFloatType() const { return false; }
816 
817 bool PointerType::IsIntType() const { return false; }
818 
819 bool PointerType::IsUnsignedType() const { return false; }
820 
821 bool PointerType::IsConstType() const { return isConst; }
822 
823 const Type *PointerType::GetBaseType() const { return baseType; }
824 
827  return this;
828  else
830 }
831 
834  return this;
835  else
837 }
838 
841  return this;
842  else
844 }
845 
846 const PointerType *PointerType::GetAsSOAType(int width) const {
847  if (GetSOAWidth() == width)
848  return this;
849  else
851 }
852 
854  if (isSlice)
855  return this;
856  return new PointerType(baseType, variability, isConst, true);
857 }
858 
860  if (isSlice == false)
861  return this;
862  return new PointerType(baseType, variability, isConst, false);
863 }
864 
866  if (isFrozen)
867  return this;
868  return new PointerType(baseType, variability, isConst, true, true);
869 }
870 
872  if (baseType == NULL) {
873  Assert(m->errorCount > 0);
874  return NULL;
875  }
876 
878  Variability ptrVariability = (variability == Variability::Unbound) ? v : variability;
879  const Type *resolvedBaseType = baseType->ResolveUnboundVariability(Variability::Uniform);
880  return new PointerType(resolvedBaseType, ptrVariability, isConst, isSlice, isFrozen);
881 }
882 
884  if (isConst == true)
885  return this;
886  else
887  return new PointerType(baseType, variability, true, isSlice);
888 }
889 
891  if (isConst == false)
892  return this;
893  else
894  return new PointerType(baseType, variability, false, isSlice);
895 }
896 
897 std::string PointerType::GetString() const {
898  if (baseType == NULL) {
899  Assert(m->errorCount > 0);
900  return "";
901  }
902 
903  std::string ret = baseType->GetString();
904 
905  ret += std::string(" * ");
906  if (isConst)
907  ret += "const ";
908  if (isSlice)
909  ret += "slice ";
910  if (isFrozen)
911  ret += "/*frozen*/ ";
912  ret += variability.GetString();
913 
914  return ret;
915 }
916 
917 std::string PointerType::Mangle() const {
919  if (baseType == NULL) {
920  Assert(m->errorCount > 0);
921  return "";
922  }
923 
924  std::string ret = variability.MangleString() + std::string("_3C_"); // <
925  if (isSlice || isFrozen)
926  ret += "-";
927  if (isSlice)
928  ret += "s";
929  if (isFrozen)
930  ret += "f";
931  if (isSlice || isFrozen)
932  ret += "-";
933  return ret + baseType->Mangle() + std::string("_3E_"); // >
934 }
935 
936 std::string PointerType::GetCDeclaration(const std::string &name) const {
938  Assert(m->errorCount > 0);
939  return "";
940  }
941 
942  if (baseType == NULL) {
943  Assert(m->errorCount > 0);
944  return "";
945  }
946 
947  bool baseIsBasicVarying = (IsBasicType(baseType)) && (baseType->IsVaryingType());
948  bool baseIsFunction = (CastType<FunctionType>(baseType) != NULL);
949 
950  std::string tempName;
951  if (baseIsBasicVarying || baseIsFunction)
952  tempName += std::string("(");
953  tempName += std::string(" *");
954  if (isConst)
955  tempName += " const";
956  tempName += std::string(" ");
957  tempName += name;
958  if (baseIsBasicVarying || baseIsFunction)
959  tempName += std::string(")");
960 
961  std::string ret;
962  if (!baseIsFunction) {
963  ret = baseType->GetCDeclaration("");
964  ret += tempName;
965  } else {
966  ret += baseType->GetCDeclaration(tempName);
967  }
968  if (variability == Variability::SOA) {
969  char buf[32];
970  snprintf(buf, sizeof(buf), "[%d]", variability.soaWidth);
971  ret += buf;
972  }
973  if (baseIsBasicVarying) {
974  int vWidth = g->target->getVectorWidth();
975  char buf[32];
976  snprintf(buf, sizeof(buf), "[%d]", vWidth);
977  ret += buf;
978  }
979 
980  return ret;
981 }
982 
983 llvm::Type *PointerType::LLVMType(llvm::LLVMContext *ctx) const {
984  if (baseType == NULL) {
985  Assert(m->errorCount > 0);
986  return NULL;
987  }
988 
989  if (isSlice) {
990  llvm::Type *types[2];
991  types[0] = GetAsNonSlice()->LLVMStorageType(ctx);
992 
993  switch (variability.type) {
995  types[1] = LLVMTypes::Int32Type;
996  break;
998  types[1] = LLVMTypes::Int32VectorType;
999  break;
1000  case Variability::SOA:
1001  types[1] = llvm::ArrayType::get(LLVMTypes::Int32Type, variability.soaWidth);
1002  break;
1003  default:
1004  FATAL("unexpected variability for slice pointer in "
1005  "PointerType::LLVMType");
1006  }
1007 
1008  llvm::ArrayRef<llvm::Type *> typesArrayRef = llvm::ArrayRef<llvm::Type *>(types, 2);
1009  return llvm::StructType::get(*g->ctx, typesArrayRef);
1010  }
1011 
1012  switch (variability.type) {
1013  case Variability::Uniform: {
1014  llvm::Type *ptype = NULL;
1015  const FunctionType *ftype = CastType<FunctionType>(baseType);
1016  if (ftype != NULL)
1017  ptype = llvm::PointerType::get(ftype->LLVMFunctionType(ctx), 0);
1018  else {
1019  if (baseType->IsVoidType())
1021  else
1022  ptype = llvm::PointerType::get(baseType->LLVMStorageType(ctx), 0);
1023  }
1024  return ptype;
1025  }
1026  case Variability::Varying:
1027  // always the same, since we currently use int vectors for varying
1028  // pointers
1030  case Variability::SOA: {
1032  return at.LLVMType(ctx);
1033  }
1034  default:
1035  FATAL("Unexpected variability in PointerType::LLVMType()");
1036  return NULL;
1037  }
1038 }
1039 
1040 llvm::DIType *PointerType::GetDIType(llvm::DIScope *scope) const {
1041  if (baseType == NULL) {
1042  Assert(m->errorCount > 0);
1043  return NULL;
1044  }
1045  llvm::DIType *diTargetType = baseType->GetDIType(scope);
1046  int bitsSize = g->target->is32Bit() ? 32 : 64;
1047  int ptrAlignBits = bitsSize;
1048  switch (variability.type) {
1049  case Variability::Uniform:
1050  return m->diBuilder->createPointerType(diTargetType, bitsSize, ptrAlignBits);
1051  case Variability::Varying: {
1052  // emit them as an array of pointers
1053  llvm::DIDerivedType *eltType = m->diBuilder->createPointerType(diTargetType, bitsSize, ptrAlignBits);
1054  return lCreateDIArray(eltType, g->target->getVectorWidth());
1055  }
1056  case Variability::SOA: {
1058  return at.GetDIType(scope);
1059  }
1060  default:
1061  FATAL("Unexpected variability in PointerType::GetDIType()");
1062  return NULL;
1063  }
1064 }
1065 
1066 ///////////////////////////////////////////////////////////////////////////
1067 // SequentialType
1068 
1069 const Type *SequentialType::GetElementType(int index) const { return GetElementType(); }
1070 
1071 ///////////////////////////////////////////////////////////////////////////
1072 // ArrayType
1073 
1074 ArrayType::ArrayType(const Type *c, int a) : SequentialType(ARRAY_TYPE), child(c), numElements(a) {
1075  // 0 -> unsized array.
1076  Assert(numElements >= 0);
1077  Assert(c->IsVoidType() == false);
1078 }
1079 
1080 llvm::ArrayType *ArrayType::LLVMType(llvm::LLVMContext *ctx) const {
1081  if (child == NULL) {
1082  Assert(m->errorCount > 0);
1083  return NULL;
1084  }
1085 
1086  llvm::Type *ct = child->LLVMStorageType(ctx);
1087  if (ct == NULL) {
1088  Assert(m->errorCount > 0);
1089  return NULL;
1090  }
1091  return llvm::ArrayType::get(ct, numElements);
1092 }
1093 
1096 }
1097 
1098 bool ArrayType::IsFloatType() const { return false; }
1099 
1100 bool ArrayType::IsIntType() const { return false; }
1101 
1102 bool ArrayType::IsUnsignedType() const { return false; }
1103 
1104 bool ArrayType::IsBoolType() const { return false; }
1105 
1106 bool ArrayType::IsConstType() const { return child ? child->IsConstType() : false; }
1107 
1109  const Type *type = child;
1110  const ArrayType *at = CastType<ArrayType>(type);
1111  // Keep walking until we reach a child that isn't itself an array
1112  while (at) {
1113  type = at->child;
1114  at = CastType<ArrayType>(type);
1115  }
1116  return type;
1117 }
1118 
1120  if (child == NULL) {
1121  Assert(m->errorCount > 0);
1122  return NULL;
1123  }
1124  return new ArrayType(child->GetAsVaryingType(), numElements);
1125 }
1126 
1128  if (child == NULL) {
1129  Assert(m->errorCount > 0);
1130  return NULL;
1131  }
1132  return new ArrayType(child->GetAsUniformType(), numElements);
1133 }
1134 
1136  if (child == NULL) {
1137  Assert(m->errorCount > 0);
1138  return NULL;
1139  }
1141 }
1142 
1143 const ArrayType *ArrayType::GetAsSOAType(int width) const {
1144  if (child == NULL) {
1145  Assert(m->errorCount > 0);
1146  return NULL;
1147  }
1148  return new ArrayType(child->GetAsSOAType(width), numElements);
1149 }
1150 
1152  if (child == NULL) {
1153  Assert(m->errorCount > 0);
1154  return NULL;
1155  }
1157 }
1158 
1160  if (child == NULL) {
1161  Assert(m->errorCount > 0);
1162  return NULL;
1163  }
1164  return new ArrayType(child->GetAsUnsignedType(), numElements);
1165 }
1166 
1168  if (child == NULL) {
1169  Assert(m->errorCount > 0);
1170  return NULL;
1171  }
1172  return new ArrayType(child->GetAsConstType(), numElements);
1173 }
1174 
1176  if (child == NULL) {
1177  Assert(m->errorCount > 0);
1178  return NULL;
1179  }
1180  return new ArrayType(child->GetAsNonConstType(), numElements);
1181 }
1182 
1184 
1185 const Type *ArrayType::GetElementType() const { return child; }
1186 
1187 std::string ArrayType::GetString() const {
1188  const Type *base = GetBaseType();
1189  if (base == NULL) {
1190  Assert(m->errorCount > 0);
1191  return "";
1192  }
1193  std::string s = base->GetString();
1194 
1195  const ArrayType *at = this;
1196  Assert(at);
1197  // Walk through this and any children arrays and print all of their
1198  // dimensions
1199  while (at) {
1200  char buf[16];
1201  if (at->numElements > 0)
1202  snprintf(buf, sizeof(buf), "%d", at->numElements);
1203  else
1204  buf[0] = '\0';
1205  s += std::string("[") + std::string(buf) + std::string("]");
1206  at = CastType<ArrayType>(at->child);
1207  }
1208  return s;
1209 }
1210 
1211 std::string ArrayType::Mangle() const {
1212  if (child == NULL) {
1213  Assert(m->errorCount > 0);
1214  return "(error)";
1215  }
1216  std::string s = child->Mangle();
1217  char buf[16];
1218  if (numElements > 0)
1219  snprintf(buf, sizeof(buf), "%d", numElements);
1220  else
1221  buf[0] = '\0';
1222  // return s + "[" + buf + "]";
1223  return s + "_5B_" + buf + "_5D_";
1224 }
1225 
1226 std::string ArrayType::GetCDeclaration(const std::string &name) const {
1227  const Type *base = GetBaseType();
1228  if (base == NULL) {
1229  Assert(m->errorCount > 0);
1230  return "";
1231  }
1232 
1233  int soaWidth = base->GetSOAWidth();
1234  int vWidth = (base->IsVaryingType()) ? g->target->getVectorWidth() : 0;
1235  base = base->GetAsUniformType();
1236 
1237  std::string s = base->GetCDeclaration(name);
1238 
1239  const ArrayType *at = this;
1240  Assert(at);
1241  while (at) {
1242  char buf[16];
1243  if (at->numElements > 0)
1244  snprintf(buf, sizeof(buf), "%d", at->numElements);
1245  else
1246  buf[0] = '\0';
1247  s += std::string("[") + std::string(buf) + std::string("]");
1248  at = CastType<ArrayType>(at->child);
1249  }
1250 
1251  if (soaWidth > 0) {
1252  char buf[16];
1253  snprintf(buf, sizeof(buf), "[%d]", soaWidth);
1254  s += buf;
1255  }
1256 
1257  if (vWidth > 0) {
1258  char buf[16];
1259  snprintf(buf, sizeof(buf), "[%d]", vWidth);
1260  s += buf;
1261  }
1262 
1263  return s;
1264 }
1265 
1267  const ArrayType *ct = CastType<ArrayType>(child);
1268  if (ct != NULL)
1269  return numElements * ct->TotalElementCount();
1270  else
1271  return numElements;
1272 }
1273 
1274 llvm::DIType *ArrayType::GetDIType(llvm::DIScope *scope) const {
1275  if (child == NULL) {
1276  Assert(m->errorCount > 0);
1277  return NULL;
1278  }
1279  llvm::DIType *eltType = child->GetDIType(scope);
1280  return lCreateDIArray(eltType, numElements);
1281 }
1282 
1284  Assert(numElements == 0);
1285  return new ArrayType(child, sz);
1286 }
1287 
1288 const Type *ArrayType::SizeUnsizedArrays(const Type *type, Expr *initExpr) {
1289  const ArrayType *at = CastType<ArrayType>(type);
1290  if (at == NULL)
1291  return type;
1292 
1293  ExprList *exprList = llvm::dyn_cast_or_null<ExprList>(initExpr);
1294  if (exprList == NULL || exprList->exprs.size() == 0)
1295  return type;
1296 
1297  // If the current dimension is unsized, then size it according to the
1298  // length of the expression list
1299  if (at->GetElementCount() == 0) {
1300  type = at->GetSizedArray(exprList->exprs.size());
1301  at = CastType<ArrayType>(type);
1302  }
1303 
1304  // Is there another nested level of expression lists? If not, bail out
1305  // now. Otherwise we'll use the first one to size the next dimension
1306  // (after checking below that it has the same length as all of the
1307  // other ones.
1308  ExprList *nextList = llvm::dyn_cast_or_null<ExprList>(exprList->exprs[0]);
1309  if (nextList == NULL)
1310  return type;
1311 
1312  const Type *nextType = at->GetElementType();
1313  const ArrayType *nextArrayType = CastType<ArrayType>(nextType);
1314  if (nextArrayType != NULL && nextArrayType->GetElementCount() == 0) {
1315  // If the recursive call to SizeUnsizedArrays at the bottom of the
1316  // function is going to size an unsized dimension, make sure that
1317  // all of the sub-expression lists are the same length--i.e. issue
1318  // an error if we have something like
1319  // int x[][] = { { 1 }, { 1, 2, 3, 4 } };
1320  unsigned int nextSize = nextList->exprs.size();
1321  for (unsigned int i = 1; i < exprList->exprs.size(); ++i) {
1322  if (exprList->exprs[i] == NULL) {
1323  // We should have seen an error earlier in this case.
1324  Assert(m->errorCount > 0);
1325  continue;
1326  }
1327 
1328  ExprList *el = llvm::dyn_cast_or_null<ExprList>(exprList->exprs[i]);
1329  if (el == NULL || el->exprs.size() != nextSize) {
1330  Error(Union(exprList->exprs[0]->pos, exprList->exprs[i]->pos),
1331  "Inconsistent initializer expression list lengths "
1332  "make it impossible to size unsized array dimensions.");
1333  return NULL;
1334  }
1335  }
1336  }
1337 
1338  // Recursively call SizeUnsizedArrays() to get the child type for the
1339  // array that we were able to size here.
1340  return new ArrayType(SizeUnsizedArrays(at->GetElementType(), nextList), at->GetElementCount());
1341 }
1342 
1343 ///////////////////////////////////////////////////////////////////////////
1344 // VectorType
1345 
1347  Assert(numElements > 0);
1348  Assert(base != NULL);
1349 }
1350 
1352 
1353 bool VectorType::IsFloatType() const { return base->IsFloatType(); }
1354 
1355 bool VectorType::IsIntType() const { return base->IsIntType(); }
1356 
1358 
1359 bool VectorType::IsBoolType() const { return base->IsBoolType(); }
1360 
1361 bool VectorType::IsConstType() const { return base->IsConstType(); }
1362 
1363 const Type *VectorType::GetBaseType() const { return base; }
1364 
1366 
1368 
1371 }
1372 
1373 const VectorType *VectorType::GetAsSOAType(int width) const {
1374  return new VectorType(base->GetAsSOAType(width), numElements);
1375 }
1376 
1379 }
1380 
1382  if (base == NULL) {
1383  Assert(m->errorCount > 0);
1384  return NULL;
1385  }
1386  return new VectorType(base->GetAsUnsignedType(), numElements);
1387 }
1388 
1390 
1392  return new VectorType(base->GetAsNonConstType(), numElements);
1393 }
1394 
1395 std::string VectorType::GetString() const {
1396  std::string s = base->GetString();
1397  char buf[16];
1398  snprintf(buf, sizeof(buf), "<%d>", numElements);
1399  return s + std::string(buf);
1400 }
1401 
1402 std::string VectorType::Mangle() const {
1403  std::string s = base->Mangle();
1404  char buf[16];
1405  snprintf(buf, sizeof(buf), "_3C_%d_3E_", numElements); // "<%d>"
1406  return s + std::string(buf);
1407 }
1408 
1409 std::string VectorType::GetCDeclaration(const std::string &name) const {
1410  std::string s = base->GetCDeclaration("");
1411  char buf[16];
1412  snprintf(buf, sizeof(buf), "%d", numElements);
1413  return s + std::string(buf) + " " + name;
1414 }
1415 
1417 
1418 const AtomicType *VectorType::GetElementType() const { return base; }
1419 
1420 static llvm::Type *lGetVectorLLVMType(llvm::LLVMContext *ctx, const VectorType *vType, bool isStorage) {
1421 
1422  const Type *base = vType->GetBaseType();
1423  int numElements = vType->GetElementCount();
1424 
1425  if (base == NULL) {
1426  Assert(m->errorCount > 0);
1427  return NULL;
1428  }
1429 
1430  llvm::Type *bt;
1431  if (isStorage)
1432  bt = base->LLVMStorageType(ctx);
1433  else
1434  bt = base->LLVMType(ctx);
1435  if (!bt)
1436  return NULL;
1437 
1438  if (base->IsUniformType())
1439  // Vectors of uniform types are laid out across LLVM vectors, with
1440  // the llvm vector size set to be a power of 2 bits in size but not less then 128 bit.
1441  // This is a roundabout way of ensuring that LLVM lays
1442  // them out into machine vector registers for the specified target
1443  // so that e.g. if we want to add two uniform 4 float
1444  // vectors, that is turned into a single addps on SSE.
1445  return llvm::VectorType::get(bt, vType->getVectorMemoryCount());
1446  else if (base->IsVaryingType())
1447  // varying types are already laid out to fill HW vector registers,
1448  // so a vector type here is just expanded out as an llvm array.
1449  return llvm::ArrayType::get(bt, vType->getVectorMemoryCount());
1450  else if (base->IsSOAType())
1451  return llvm::ArrayType::get(bt, numElements);
1452  else {
1453  FATAL("Unexpected variability in lGetVectorLLVMType()");
1454  return NULL;
1455  }
1456 }
1457 
1458 llvm::Type *VectorType::LLVMStorageType(llvm::LLVMContext *ctx) const { return lGetVectorLLVMType(ctx, this, true); }
1459 
1460 llvm::Type *VectorType::LLVMType(llvm::LLVMContext *ctx) const { return lGetVectorLLVMType(ctx, this, false); }
1461 
1462 llvm::DIType *VectorType::GetDIType(llvm::DIScope *scope) const {
1463  llvm::DIType *eltType = base->GetDIType(scope);
1464 
1465  llvm::Metadata *sub = m->diBuilder->getOrCreateSubrange(0, numElements);
1466 
1467  // vectors of varying types are already naturally aligned to the
1468  // machine's vector width, but arrays of uniform types need to be
1469  // explicitly aligned to the machines natural vector alignment.
1470 
1471  llvm::DINodeArray subArray = m->diBuilder->getOrCreateArray(sub);
1472  uint64_t sizeBits = eltType->getSizeInBits() * numElements;
1473  uint64_t align = eltType->getAlignInBits();
1474 
1475  if (IsUniformType()) {
1476  llvm::Type *ty = this->LLVMType(g->ctx);
1477  align = g->target->getDataLayout()->getABITypeAlignment(ty);
1478  }
1479 
1480  if (IsUniformType() || IsVaryingType())
1481  return m->diBuilder->createVectorType(sizeBits, align, eltType, subArray);
1482  else if (IsSOAType()) {
1483  ArrayType at(base, numElements);
1484  return at.GetDIType(scope);
1485  } else {
1486  FATAL("Unexpected variability in VectorType::GetDIType()");
1487  return NULL;
1488  }
1489 }
1490 
1492  if (base->IsVaryingType())
1493  return numElements;
1494  else if (base->IsUniformType()) {
1495  if (g->target->getDataTypeWidth() == -1) {
1496  // For generic targets just return correct result,
1497  // we don't care about optimizations in this case.
1498  // Should we just assume data type width equal to 32?
1499  return numElements;
1500  }
1501  // Round up the element count to power of 2 bits in size but not less then 128 bit in total vector size
1502  // where one element size is data type width in bits.
1503  // This strategy was chosen by the following reasons:
1504  // 1. We need to return the same number of vector elements regardless the element size for correct work of the
1505  // language.
1506  // 2. Using next power of two, but not less than 128 bit in total vector size ensures that machine vector
1507  // registers are used. It generally leads to better performance. This strategy also matches OpenCL short
1508  // vectors.
1509  // 3. Using data type width of the target to determine element size makes optimization trade off.
1510  int nextPow2 = llvm::NextPowerOf2(numElements - 1);
1511  return (nextPow2 * g->target->getDataTypeWidth() < 128) ? (128 / g->target->getDataTypeWidth()) : nextPow2;
1512  } else if (base->IsSOAType()) {
1513  FATAL("VectorType SOA getVectorMemoryCount");
1514  return -1;
1515  } else {
1516  FATAL("Unexpected variability in VectorType::getVectorMemoryCount()");
1517  return -1;
1518  }
1519 }
1520 
1521 ///////////////////////////////////////////////////////////////////////////
1522 // StructType
1523 
1524 // We maintain a map from struct names to LLVM struct types so that we can
1525 // uniquely get the llvm::StructType * for a given ispc struct type. Note
1526 // that we need to mangle the name a bit so that we can e.g. differentiate
1527 // between the uniform and varying variants of a given struct type. This
1528 // is handled by lMangleStructName() below.
1529 static std::map<std::string, llvm::StructType *> lStructTypeMap;
1530 
1531 /** Using a struct's name, its variability, and the vector width for the
1532  current compilation target, this function generates a string that
1533  encodes that full structure type, for use in the lStructTypeMap. Note
1534  that the vector width is needed in order to differentiate between
1535  'varying' structs with different compilation targets, which have
1536  different memory layouts...
1537  */
1538 static std::string lMangleStructName(const std::string &name, Variability variability) {
1539  char buf[32];
1540  std::string n;
1541 
1542  // Encode vector width
1543  snprintf(buf, sizeof(buf), "v%d", g->target->getVectorWidth());
1544 
1545  n += buf;
1546 
1547  // Variability
1548  switch (variability.type) {
1549  case Variability::Uniform:
1550  n += "_uniform_";
1551  break;
1552  case Variability::Varying:
1553  n += "_varying_";
1554  break;
1555  case Variability::SOA:
1556  snprintf(buf, sizeof(buf), "_soa%d_", variability.soaWidth);
1557  n += buf;
1558  break;
1559  default:
1560  FATAL("Unexpected variability in lMangleStructName()");
1561  }
1562 
1563  // And stuff the name at the end....
1564  n += name;
1565  return n;
1566 }
1567 
1568 StructType::StructType(const std::string &n, const llvm::SmallVector<const Type *, 8> &elts,
1569  const llvm::SmallVector<std::string, 8> &en, const llvm::SmallVector<SourcePos, 8> &ep, bool ic,
1570  Variability v, SourcePos p)
1571  : CollectionType(STRUCT_TYPE), name(n), elementTypes(elts), elementNames(en), elementPositions(ep), variability(v),
1572  isConst(ic), pos(p) {
1573  oppositeConstStructType = NULL;
1574  finalElementTypes.resize(elts.size(), NULL);
1575 
1577  // For structs with non-unbound variability, we'll create the
1578  // correspoing LLVM struct type now, if one hasn't been made
1579  // already.
1580 
1581  // Create a unique anonymous struct name if we have an anonymous
1582  // struct (name == ""), or if we are creating a derived type from
1583  // an anonymous struct (e.g. the varying variant--name == '$').
1584  if (name == "" || name[0] == '$') {
1585  char buf[16];
1586  static int count = 0;
1587  snprintf(buf, sizeof(buf), "$anon%d", count);
1588  name = std::string(buf);
1589  ++count;
1590  }
1591 
1592  // If a non-opaque LLVM struct for this type has already been
1593  // created, we're done. For an opaque struct type, we'll override
1594  // the old definition now that we have a full definition.
1595  std::string mname = lMangleStructName(name, variability);
1596  if (lStructTypeMap.find(mname) != lStructTypeMap.end() && lStructTypeMap[mname]->isOpaque() == false)
1597  return;
1598 
1599  // Actually make the LLVM struct
1600  std::vector<llvm::Type *> elementTypes;
1601  int nElements = GetElementCount();
1602  if (nElements == 0) {
1603  elementTypes.push_back(LLVMTypes::Int8Type);
1604  } else {
1605  for (int i = 0; i < nElements; ++i) {
1606  const Type *type = GetElementType(i);
1607  if (type == NULL) {
1608  Assert(m->errorCount > 0);
1609  return;
1610  } else if (CastType<FunctionType>(type) != NULL) {
1611  Error(elementPositions[i], "Method declarations are not "
1612  "supported.");
1613  return;
1614  } else
1615  elementTypes.push_back(type->LLVMStorageType(g->ctx));
1616  }
1617  }
1618 
1619  if (lStructTypeMap.find(mname) == lStructTypeMap.end()) {
1620  // New struct definition
1621  llvm::StructType *st = llvm::StructType::create(*g->ctx, elementTypes, mname);
1622  lStructTypeMap[mname] = st;
1623  } else {
1624  // Definition for what was before just a declaration
1625  lStructTypeMap[mname]->setBody(elementTypes);
1626  }
1627  }
1628 }
1629 
1630 const std::string StructType::GetCStructName() const {
1631  // only return mangled name for varying structs for backwards
1632  // compatibility...
1633 
1636  } else {
1637  return GetStructName();
1638  }
1639 }
1640 
1642 
1643 bool StructType::IsBoolType() const { return false; }
1644 
1645 bool StructType::IsFloatType() const { return false; }
1646 
1647 bool StructType::IsIntType() const { return false; }
1648 
1649 bool StructType::IsUnsignedType() const { return false; }
1650 
1651 bool StructType::IsConstType() const { return isConst; }
1652 
1654  for (int i = 0; i < GetElementCount(); i++) {
1655  const Type *t = GetElementType(i);
1656  const UndefinedStructType *ust = CastType<UndefinedStructType>(t);
1657  if (ust != NULL) {
1658  return false;
1659  }
1660  const StructType *st = CastType<StructType>(t);
1661  if (st != NULL) {
1662  if (!st->IsDefined()) {
1663  return false;
1664  }
1665  }
1666  }
1667  return true;
1668 }
1669 
1670 const Type *StructType::GetBaseType() const { return this; }
1671 
1673  if (IsVaryingType())
1674  return this;
1675  else
1678 }
1679 
1681  if (IsUniformType())
1682  return this;
1683  else
1686 }
1687 
1689  if (HasUnboundVariability())
1690  return this;
1691  else
1694 }
1695 
1696 const StructType *StructType::GetAsSOAType(int width) const {
1697  if (GetSOAWidth() == width)
1698  return this;
1699 
1700  if (checkIfCanBeSOA(this) == false)
1701  return NULL;
1702 
1704  Variability(Variability::SOA, width), pos);
1705 }
1706 
1709 
1711  return this;
1712 
1713  // We don't resolve the members here but leave them unbound, so that if
1714  // resolve to varying but later want to get the uniform version of this
1715  // type, for example, then we still have the information around about
1716  // which element types were originally unbound...
1718 }
1719 
1721  if (isConst == true)
1722  return this;
1723  else if (oppositeConstStructType != NULL)
1724  return oppositeConstStructType;
1725  else {
1729  return oppositeConstStructType;
1730  }
1731 }
1732 
1734  if (isConst == false)
1735  return this;
1736  else if (oppositeConstStructType != NULL)
1737  return oppositeConstStructType;
1738  else {
1742  return oppositeConstStructType;
1743  }
1744 }
1745 
1746 std::string StructType::GetString() const {
1747  std::string ret;
1748  if (isConst)
1749  ret += "const ";
1750  ret += variability.GetString();
1751  ret += " ";
1752 
1753  if (name[0] == '$') {
1754  // Print the whole anonymous struct declaration
1755  ret += std::string("struct { ") + name;
1756  for (unsigned int i = 0; i < elementTypes.size(); ++i) {
1757  ret += elementTypes[i]->GetString();
1758  ret += " ";
1759  ret += elementNames[i];
1760  ret += "; ";
1761  }
1762  ret += "}";
1763  } else {
1764  ret += "struct ";
1765  ret += name;
1766  }
1767 
1768  return ret;
1769 }
1770 
1771 /** Mangle a struct name for use in function name mangling. */
1772 static std::string lMangleStruct(Variability variability, bool isConst, const std::string &name) {
1773  Assert(variability != Variability::Unbound);
1774 
1775  std::string ret;
1776  // ret += "s[";
1777  ret += "s_5B_";
1778  if (isConst)
1779  ret += "_c_";
1780  ret += variability.MangleString();
1781 
1782  // ret += name + std::string("]");
1783  ret += name + std::string("_5D_");
1784  return ret;
1785 }
1786 
1787 std::string StructType::Mangle() const { return lMangleStruct(variability, isConst, name); }
1788 
1789 std::string StructType::GetCDeclaration(const std::string &n) const {
1790  std::string ret;
1791  if (isConst)
1792  ret += "const ";
1793  ret += std::string("struct ") + GetCStructName();
1794  if (lShouldPrintName(n)) {
1795  ret += std::string(" ") + n;
1796 
1797  if (variability.soaWidth > 0) {
1798  char buf[32];
1799  // This has to match the naming scheme used in lEmitStructDecls()
1800  // in module.cpp
1801  snprintf(buf, sizeof(buf), "_SOA%d", variability.soaWidth);
1802  ret += buf;
1803  }
1804  }
1805 
1806  return ret;
1807 }
1808 
1809 llvm::Type *StructType::LLVMType(llvm::LLVMContext *ctx) const {
1811  std::string mname = lMangleStructName(name, variability);
1812  if (lStructTypeMap.find(mname) == lStructTypeMap.end()) {
1813  Assert(m->errorCount > 0);
1814  return NULL;
1815  }
1816  return lStructTypeMap[mname];
1817 }
1818 
1819 // Versioning of this function becomes really messy, so versioning the whole function.
1820 llvm::DIType *StructType::GetDIType(llvm::DIScope *scope) const {
1821  llvm::Type *llvm_type = LLVMStorageType(g->ctx);
1822  auto &dataLayout = m->module->getDataLayout();
1823  auto layout = dataLayout.getStructLayout(llvm::dyn_cast_or_null<llvm::StructType>(llvm_type));
1824  std::vector<llvm::Metadata *> elementLLVMTypes;
1825  // Walk through the elements of the struct; for each one figure out its
1826  // alignment and size, using that to figure out its offset w.r.t. the
1827  // start of the structure.
1828  for (unsigned int i = 0; i < elementTypes.size(); ++i) {
1829  llvm::DIType *eltType = GetElementType(i)->GetDIType(scope);
1830  uint64_t eltSize = eltType->getSizeInBits();
1831 
1832  auto llvmType = GetElementType(i)->LLVMStorageType(g->ctx);
1833  uint64_t eltAlign = dataLayout.getABITypeAlignment(llvmType) * 8;
1834  Assert(eltAlign != 0);
1835 
1836  auto eltOffset = layout->getElementOffsetInBits(i);
1837 
1838  int line = elementPositions[i].first_line;
1839  llvm::DIFile *diFile = elementPositions[i].GetDIFile();
1840  llvm::DIDerivedType *fieldType = m->diBuilder->createMemberType(
1841  scope, elementNames[i], diFile, line, eltSize, eltAlign, eltOffset, llvm::DINode::FlagZero, eltType);
1842  elementLLVMTypes.push_back(fieldType);
1843  }
1844 
1845  llvm::DINodeArray elements = m->diBuilder->getOrCreateArray(elementLLVMTypes);
1846  llvm::DIFile *diFile = pos.GetDIFile();
1847  return m->diBuilder->createStructType(diFile, name, diFile,
1848  pos.first_line, // Line number
1849  layout->getSizeInBits(), // Size in bits
1850 #if ISPC_LLVM_VERSION <= ISPC_LLVM_9_0
1851  layout->getAlignment() * 8, // Alignment in bits
1852 #else // LLVM 10.0+
1853  layout->getAlignment().value() * 8, // Alignment in bits
1854 #endif
1855  llvm::DINode::FlagZero, // Flags
1856  NULL, elements);
1857 }
1858 
1859 const Type *StructType::GetElementType(int i) const {
1861  Assert(i < (int)elementTypes.size());
1862 
1863  if (finalElementTypes[i] == NULL) {
1864  const Type *type = elementTypes[i];
1865  if (type == NULL) {
1866  Assert(m->errorCount > 0);
1867  return NULL;
1868  }
1869 
1870  // If the element has unbound variability, resolve its variability to
1871  // the struct type's variability
1872  type = type->ResolveUnboundVariability(variability);
1873  if (isConst)
1874  type = type->GetAsConstType();
1875  finalElementTypes[i] = type;
1876  }
1877 
1878  return finalElementTypes[i];
1879 }
1880 
1881 const Type *StructType::GetElementType(const std::string &n) const {
1882  for (unsigned int i = 0; i < elementNames.size(); ++i)
1883  if (elementNames[i] == n)
1884  return GetElementType(i);
1885  return NULL;
1886 }
1887 
1888 int StructType::GetElementNumber(const std::string &n) const {
1889  for (unsigned int i = 0; i < elementNames.size(); ++i)
1890  if (elementNames[i] == n)
1891  return i;
1892  return -1;
1893 }
1894 
1896  bool ok = true;
1897  for (int i = 0; i < (int)st->elementTypes.size(); ++i) {
1898  const Type *eltType = st->elementTypes[i];
1899  const StructType *childStructType = CastType<StructType>(eltType);
1900 
1901  if (childStructType != NULL)
1902  ok &= checkIfCanBeSOA(childStructType);
1903  else if (eltType->HasUnboundVariability() == false) {
1904  Error(st->elementPositions[i],
1905  "Unable to apply SOA conversion to "
1906  "struct due to \"%s\" member \"%s\" with bound \"%s\" "
1907  "variability.",
1908  eltType->GetString().c_str(), st->elementNames[i].c_str(),
1909  eltType->IsUniformType() ? "uniform" : "varying");
1910  ok = false;
1911  } else if (CastType<ReferenceType>(eltType)) {
1912  Error(st->elementPositions[i],
1913  "Unable to apply SOA conversion to "
1914  "struct due to member \"%s\" with reference type \"%s\".",
1915  st->elementNames[i].c_str(), eltType->GetString().c_str());
1916  ok = false;
1917  }
1918  }
1919  return ok;
1920 }
1921 
1922 ///////////////////////////////////////////////////////////////////////////
1923 // UndefinedStructType
1924 
1925 UndefinedStructType::UndefinedStructType(const std::string &n, const Variability var, bool ic, SourcePos p)
1926  : Type(UNDEFINED_STRUCT_TYPE), name(n), variability(var), isConst(ic), pos(p) {
1927  Assert(name != "");
1929  // Create a new opaque LLVM struct type for this struct name
1930  std::string mname = lMangleStructName(name, variability);
1931  if (lStructTypeMap.find(mname) == lStructTypeMap.end())
1932  lStructTypeMap[mname] = llvm::StructType::create(*g->ctx, mname);
1933  }
1934 }
1935 
1937 
1938 bool UndefinedStructType::IsBoolType() const { return false; }
1939 
1940 bool UndefinedStructType::IsFloatType() const { return false; }
1941 
1942 bool UndefinedStructType::IsIntType() const { return false; }
1943 
1944 bool UndefinedStructType::IsUnsignedType() const { return false; }
1945 
1947 
1948 const Type *UndefinedStructType::GetBaseType() const { return this; }
1949 
1952  return this;
1954 }
1955 
1958  return this;
1960 }
1961 
1964  return this;
1966 }
1967 
1969  FATAL("UndefinedStructType::GetAsSOAType() shouldn't be called.");
1970  return NULL;
1971 }
1972 
1975  return this;
1976  return new UndefinedStructType(name, v, isConst, pos);
1977 }
1978 
1980  if (isConst)
1981  return this;
1982  return new UndefinedStructType(name, variability, true, pos);
1983 }
1984 
1986  if (isConst == false)
1987  return this;
1988  return new UndefinedStructType(name, variability, false, pos);
1989 }
1990 
1991 std::string UndefinedStructType::GetString() const {
1992  std::string ret;
1993  if (isConst)
1994  ret += "const ";
1995  ret += variability.GetString();
1996  ret += " struct ";
1997  ret += name;
1998  return ret;
1999 }
2000 
2002 
2003 std::string UndefinedStructType::GetCDeclaration(const std::string &n) const {
2004  std::string ret;
2005  if (isConst)
2006  ret += "const ";
2007  ret += std::string("struct ") + name;
2008  if (lShouldPrintName(n))
2009  ret += std::string(" ") + n;
2010  return ret;
2011 }
2012 
2013 llvm::Type *UndefinedStructType::LLVMType(llvm::LLVMContext *ctx) const {
2015  std::string mname = lMangleStructName(name, variability);
2016  if (lStructTypeMap.find(mname) == lStructTypeMap.end()) {
2017  Assert(m->errorCount > 0);
2018  return NULL;
2019  }
2020  return lStructTypeMap[mname];
2021 }
2022 
2023 llvm::DIType *UndefinedStructType::GetDIType(llvm::DIScope *scope) const {
2024  llvm::DIFile *diFile = pos.GetDIFile();
2025  llvm::DINodeArray elements;
2026  return m->diBuilder->createStructType(diFile, name, diFile,
2027  pos.first_line, // Line number
2028  0, // Size
2029  0, // Align
2030  llvm::DINode::FlagZero, // Flags
2031  NULL, elements);
2032 }
2033 
2034 ///////////////////////////////////////////////////////////////////////////
2035 // ReferenceType
2036 
2038 
2040  if (targetType == NULL) {
2041  Assert(m->errorCount > 0);
2043  }
2044  return targetType->GetVariability();
2045 }
2046 
2048  if (targetType == NULL) {
2049  Assert(m->errorCount > 0);
2050  return false;
2051  }
2052  return targetType->IsBoolType();
2053 }
2054 
2056  if (targetType == NULL) {
2057  Assert(m->errorCount > 0);
2058  return false;
2059  }
2060  return targetType->IsFloatType();
2061 }
2062 
2064  if (targetType == NULL) {
2065  Assert(m->errorCount > 0);
2066  return false;
2067  }
2068  return targetType->IsIntType();
2069 }
2070 
2072  if (targetType == NULL) {
2073  Assert(m->errorCount > 0);
2074  return false;
2075  }
2076  return targetType->IsUnsignedType();
2077 }
2078 
2080  if (targetType == NULL) {
2081  Assert(m->errorCount > 0);
2082  return false;
2083  }
2084  return targetType->IsConstType();
2085 }
2086 
2088 
2090  if (targetType == NULL) {
2091  Assert(m->errorCount > 0);
2092  return NULL;
2093  }
2094  return targetType->GetBaseType();
2095 }
2096 
2098  if (targetType == NULL) {
2099  Assert(m->errorCount > 0);
2100  return NULL;
2101  }
2102  if (IsVaryingType())
2103  return this;
2104  return new ReferenceType(targetType->GetAsVaryingType());
2105 }
2106 
2108  if (targetType == NULL) {
2109  Assert(m->errorCount > 0);
2110  return NULL;
2111  }
2112  if (IsUniformType())
2113  return this;
2114  return new ReferenceType(targetType->GetAsUniformType());
2115 }
2116 
2118  if (targetType == NULL) {
2119  Assert(m->errorCount > 0);
2120  return NULL;
2121  }
2122  if (HasUnboundVariability())
2123  return this;
2125 }
2126 
2127 const Type *ReferenceType::GetAsSOAType(int width) const {
2128  // FIXME: is this right?
2129  return new ArrayType(this, width);
2130 }
2131 
2133  if (targetType == NULL) {
2134  Assert(m->errorCount > 0);
2135  return NULL;
2136  }
2138 }
2139 
2141  if (targetType == NULL) {
2142  Assert(m->errorCount > 0);
2143  return NULL;
2144  }
2145  if (IsConstType())
2146  return this;
2147 
2148  if (asOtherConstType == NULL) {
2151  }
2152  return asOtherConstType;
2153 }
2154 
2156  if (targetType == NULL) {
2157  Assert(m->errorCount > 0);
2158  return NULL;
2159  }
2160  if (!IsConstType())
2161  return this;
2162 
2163  if (asOtherConstType == NULL) {
2166  }
2167  return asOtherConstType;
2168 }
2169 
2170 std::string ReferenceType::GetString() const {
2171  if (targetType == NULL) {
2172  Assert(m->errorCount > 0);
2173  return "";
2174  }
2175 
2176  std::string ret = targetType->GetString();
2177 
2178  ret += std::string(" &");
2179  return ret;
2180 }
2181 
2182 std::string ReferenceType::Mangle() const {
2183  if (targetType == NULL) {
2184  Assert(m->errorCount > 0);
2185  return "";
2186  }
2187  std::string ret;
2188  ret += std::string("REF") + targetType->Mangle();
2189  return ret;
2190 }
2191 
2192 std::string ReferenceType::GetCDeclaration(const std::string &name) const {
2193  if (targetType == NULL) {
2194  Assert(m->errorCount > 0);
2195  return "";
2196  }
2197 
2198  const ArrayType *at = CastType<ArrayType>(targetType);
2199  if (at != NULL) {
2200  if (at->GetElementCount() == 0) {
2201  // emit unsized arrays as pointers to the base type..
2202  std::string ret;
2203  ret += at->GetElementType()->GetAsNonConstType()->GetCDeclaration("") + std::string(" *");
2204  if (lShouldPrintName(name))
2205  ret += name;
2206  return ret;
2207  } else
2208  // otherwise forget about the reference part if it's an
2209  // array since C already passes arrays by reference...
2210  return targetType->GetCDeclaration(name);
2211  } else {
2212  std::string ret;
2213  ret += targetType->GetCDeclaration("") + std::string(" &");
2214  if (lShouldPrintName(name))
2215  ret += name;
2216  return ret;
2217  }
2218 }
2219 
2220 llvm::Type *ReferenceType::LLVMType(llvm::LLVMContext *ctx) const {
2221  if (targetType == NULL) {
2222  Assert(m->errorCount > 0);
2223  return NULL;
2224  }
2225 
2226  llvm::Type *t = targetType->LLVMStorageType(ctx);
2227  if (t == NULL) {
2228  Assert(m->errorCount > 0);
2229  return NULL;
2230  }
2231 
2232  return llvm::PointerType::get(t, 0);
2233 }
2234 
2235 llvm::DIType *ReferenceType::GetDIType(llvm::DIScope *scope) const {
2236  if (targetType == NULL) {
2237  Assert(m->errorCount > 0);
2238  return NULL;
2239  }
2240  llvm::DIType *diTargetType = targetType->GetDIType(scope);
2241  return m->diBuilder->createReferenceType(llvm::dwarf::DW_TAG_reference_type, diTargetType);
2242 }
2243 
2244 ///////////////////////////////////////////////////////////////////////////
2245 // FunctionType
2246 
2247 FunctionType::FunctionType(const Type *r, const llvm::SmallVector<const Type *, 8> &a, SourcePos p)
2248  : Type(FUNCTION_TYPE), isTask(false), isExported(false), isExternC(false), isUnmasked(false), returnType(r),
2249  paramTypes(a), paramNames(llvm::SmallVector<std::string, 8>(a.size(), "")),
2250  paramDefaults(llvm::SmallVector<Expr *, 8>(a.size(), NULL)),
2251  paramPositions(llvm::SmallVector<SourcePos, 8>(a.size(), p)) {
2252  Assert(returnType != NULL);
2253  isSafe = false;
2254  costOverride = -1;
2255 }
2256 
2257 FunctionType::FunctionType(const Type *r, const llvm::SmallVector<const Type *, 8> &a,
2258  const llvm::SmallVector<std::string, 8> &an, const llvm::SmallVector<Expr *, 8> &ad,
2259  const llvm::SmallVector<SourcePos, 8> &ap, bool it, bool is, bool ec, bool ium)
2260  : Type(FUNCTION_TYPE), isTask(it), isExported(is), isExternC(ec), isUnmasked(ium), returnType(r), paramTypes(a),
2261  paramNames(an), paramDefaults(ad), paramPositions(ap) {
2262  Assert(paramTypes.size() == paramNames.size() && paramNames.size() == paramDefaults.size() &&
2263  paramDefaults.size() == paramPositions.size());
2264  Assert(returnType != NULL);
2265  isSafe = false;
2266  costOverride = -1;
2267 }
2268 
2270 
2271 bool FunctionType::IsFloatType() const { return false; }
2272 
2273 bool FunctionType::IsIntType() const { return false; }
2274 
2275 bool FunctionType::IsBoolType() const { return false; }
2276 
2277 bool FunctionType::IsUnsignedType() const { return false; }
2278 
2279 bool FunctionType::IsConstType() const { return false; }
2280 
2282  FATAL("FunctionType::GetBaseType() shouldn't be called");
2283  return NULL;
2284 }
2285 
2287  FATAL("FunctionType::GetAsVaryingType shouldn't be called");
2288  return NULL;
2289 }
2290 
2292  FATAL("FunctionType::GetAsUniformType shouldn't be called");
2293  return NULL;
2294 }
2295 
2297  FATAL("FunctionType::GetAsUnboundVariabilityType shouldn't be called");
2298  return NULL;
2299 }
2300 
2301 const Type *FunctionType::GetAsSOAType(int width) const {
2302  FATAL("FunctionType::GetAsSOAType() shouldn't be called");
2303  return NULL;
2304 }
2305 
2307  if (returnType == NULL) {
2308  Assert(m->errorCount > 0);
2309  return NULL;
2310  }
2311  const Type *rt = returnType->ResolveUnboundVariability(v);
2312 
2313  llvm::SmallVector<const Type *, 8> pt;
2314  for (unsigned int i = 0; i < paramTypes.size(); ++i) {
2315  if (paramTypes[i] == NULL) {
2316  Assert(m->errorCount > 0);
2317  return NULL;
2318  }
2319  pt.push_back(paramTypes[i]->ResolveUnboundVariability(v));
2320  }
2321 
2322  FunctionType *ret =
2324  ret->isSafe = isSafe;
2325  ret->costOverride = costOverride;
2326 
2327  return ret;
2328 }
2329 
2330 const Type *FunctionType::GetAsConstType() const { return this; }
2331 
2332 const Type *FunctionType::GetAsNonConstType() const { return this; }
2333 
2334 std::string FunctionType::GetString() const {
2335  std::string ret = GetReturnTypeString();
2336  ret += "(";
2337  for (unsigned int i = 0; i < paramTypes.size(); ++i) {
2338  if (paramTypes[i] == NULL)
2339  ret += "/* ERROR */";
2340  else
2341  ret += paramTypes[i]->GetString();
2342 
2343  if (i != paramTypes.size() - 1)
2344  ret += ", ";
2345  }
2346  ret += ")";
2347  return ret;
2348 }
2349 
2350 std::string FunctionType::Mangle() const {
2351  std::string ret = "___";
2352  if (isUnmasked)
2353  ret += "UM_";
2354 
2355  for (unsigned int i = 0; i < paramTypes.size(); ++i)
2356  if (paramTypes[i] == NULL)
2357  Assert(m->errorCount > 0);
2358  else
2359  ret += paramTypes[i]->Mangle();
2360 
2361  return ret;
2362 }
2363 
2364 std::string FunctionType::GetCDeclaration(const std::string &fname) const {
2365  std::string ret;
2366  ret += returnType->GetCDeclaration("");
2367  ret += " ";
2368  ret += fname;
2369  ret += "(";
2370  for (unsigned int i = 0; i < paramTypes.size(); ++i) {
2371  const Type *type = paramTypes[i];
2372 
2373  // Convert pointers to arrays to unsized arrays, which are more clear
2374  // to print out for multidimensional arrays (i.e. "float foo[][4] "
2375  // versus "float (foo *)[4]").
2376  const PointerType *pt = CastType<PointerType>(type);
2377  if (pt != NULL && CastType<ArrayType>(pt->GetBaseType()) != NULL) {
2378  type = new ArrayType(pt->GetBaseType(), 0);
2379  }
2380 
2381  if (paramNames[i] != "")
2382  ret += type->GetCDeclaration(paramNames[i]);
2383  else
2384  ret += type->GetString();
2385  if (i != paramTypes.size() - 1)
2386  ret += ", ";
2387  }
2388  ret += ")";
2389  return ret;
2390 }
2391 
2392 std::string FunctionType::GetCDeclarationForDispatch(const std::string &fname) const {
2393  std::string ret;
2394  ret += returnType->GetCDeclaration("");
2395  ret += " ";
2396  ret += fname;
2397  ret += "(";
2398  for (unsigned int i = 0; i < paramTypes.size(); ++i) {
2399  const Type *type = paramTypes[i];
2400 
2401  // Convert pointers to arrays to unsized arrays, which are more clear
2402  // to print out for multidimensional arrays (i.e. "float foo[][4] "
2403  // versus "float (foo *)[4]").
2404  const PointerType *pt = CastType<PointerType>(type);
2405  if (pt != NULL && CastType<ArrayType>(pt->GetBaseType()) != NULL) {
2406  type = new ArrayType(pt->GetBaseType(), 0);
2407  }
2408 
2409  // Change pointers to varying thingies to void *
2410  if (pt != NULL && pt->GetBaseType()->IsVaryingType()) {
2412 
2413  if (paramNames[i] != "")
2414  ret += t->GetCDeclaration(paramNames[i]);
2415  else
2416  ret += t->GetString();
2417  } else {
2418  if (paramNames[i] != "")
2419  ret += type->GetCDeclaration(paramNames[i]);
2420  else
2421  ret += type->GetString();
2422  }
2423  if (i != paramTypes.size() - 1)
2424  ret += ", ";
2425  }
2426  ret += ")";
2427  return ret;
2428 }
2429 
2430 llvm::Type *FunctionType::LLVMType(llvm::LLVMContext *ctx) const {
2431  FATAL("FunctionType::LLVMType() shouldn't be called");
2432  return NULL;
2433 }
2434 
2435 llvm::DIType *FunctionType::GetDIType(llvm::DIScope *scope) const {
2436 
2437  std::vector<llvm::Metadata *> retArgTypes;
2438  retArgTypes.push_back(returnType->GetDIType(scope));
2439  for (int i = 0; i < GetNumParameters(); ++i) {
2440  const Type *t = GetParameterType(i);
2441  if (t == NULL)
2442 
2443  return NULL;
2444  retArgTypes.push_back(t->GetDIType(scope));
2445  }
2446 
2447  llvm::DITypeRefArray retArgTypesArray = m->diBuilder->getOrCreateTypeArray(retArgTypes);
2448  llvm::DIType *diType = m->diBuilder->createSubroutineType(retArgTypesArray);
2449  return diType;
2450 }
2451 
2452 const std::string FunctionType::GetReturnTypeString() const {
2453  if (returnType == NULL)
2454  return "/* ERROR */";
2455 
2456  std::string ret;
2457  if (isTask)
2458  ret += "task ";
2459  if (isExported)
2460  ret += "export ";
2461  if (isExternC)
2462  ret += "extern \"C\" ";
2463  if (isUnmasked)
2464  ret += "unmasked ";
2465  if (isSafe)
2466  ret += "/*safe*/ ";
2467  if (costOverride > 0) {
2468  char buf[32];
2469  snprintf(buf, sizeof(buf), "/*cost=%d*/ ", costOverride);
2470  ret += buf;
2471  }
2472 
2473  return ret + returnType->GetString();
2474 }
2475 
2476 llvm::FunctionType *FunctionType::LLVMFunctionType(llvm::LLVMContext *ctx, bool removeMask) const {
2477  if (isTask == true)
2478  Assert(removeMask == false);
2479 
2480  // Get the LLVM Type *s for the function arguments
2481  std::vector<llvm::Type *> llvmArgTypes;
2482  for (unsigned int i = 0; i < paramTypes.size(); ++i) {
2483  if (paramTypes[i] == NULL) {
2484  Assert(m->errorCount > 0);
2485  return NULL;
2486  }
2487  Assert(paramTypes[i]->IsVoidType() == false);
2488 
2489  const Type *argType = paramTypes[i];
2490  llvm::Type *t = argType->LLVMType(ctx);
2491  if (t == NULL) {
2492  Assert(m->errorCount > 0);
2493  return NULL;
2494  }
2495  llvmArgTypes.push_back(t);
2496  }
2497 
2498  // And add the function mask, if asked for
2499  if (!(removeMask || isUnmasked))
2500  llvmArgTypes.push_back(LLVMTypes::MaskType);
2501 
2502  std::vector<llvm::Type *> callTypes;
2503  if (isTask) {
2504  // Tasks take three arguments: a pointer to a struct that holds the
2505  // actual task arguments, the thread index, and the total number of
2506  // threads the tasks system has running. (Task arguments are
2507  // marshalled in a struct so that it's easy to allocate space to
2508  // hold them until the task actually runs.)
2509  llvm::Type *st = llvm::StructType::get(*ctx, llvmArgTypes);
2510  callTypes.push_back(llvm::PointerType::getUnqual(st));
2511  callTypes.push_back(LLVMTypes::Int32Type); // threadIndex
2512  callTypes.push_back(LLVMTypes::Int32Type); // threadCount
2513  callTypes.push_back(LLVMTypes::Int32Type); // taskIndex
2514  callTypes.push_back(LLVMTypes::Int32Type); // taskCount
2515  callTypes.push_back(LLVMTypes::Int32Type); // taskIndex0
2516  callTypes.push_back(LLVMTypes::Int32Type); // taskIndex1
2517  callTypes.push_back(LLVMTypes::Int32Type); // taskIndex2
2518  callTypes.push_back(LLVMTypes::Int32Type); // taskCount0
2519  callTypes.push_back(LLVMTypes::Int32Type); // taskCount1
2520  callTypes.push_back(LLVMTypes::Int32Type); // taskCount2
2521  } else
2522  // Otherwise we already have the types of the arguments
2523  callTypes = llvmArgTypes;
2524 
2525  if (returnType == NULL) {
2526  Assert(m->errorCount > 0);
2527  return NULL;
2528  }
2529 
2530  bool isStorageType = false;
2531  if (CastType<AtomicType>(returnType) == NULL)
2532  isStorageType = true;
2533  const Type *retType = returnType;
2534 
2535  llvm::Type *llvmReturnType = retType->LLVMType(g->ctx);
2536  if (llvmReturnType == NULL)
2537  return NULL;
2538  return llvm::FunctionType::get(llvmReturnType, callTypes, false);
2539 }
2540 
2542  Assert(i < (int)paramTypes.size());
2543  return paramTypes[i];
2544 }
2545 
2547  Assert(i < (int)paramDefaults.size());
2548  return paramDefaults[i];
2549 }
2550 
2552  Assert(i < (int)paramPositions.size());
2553  return paramPositions[i];
2554 }
2555 
2556 const std::string &FunctionType::GetParameterName(int i) const {
2557  Assert(i < (int)paramNames.size());
2558  return paramNames[i];
2559 }
2560 
2561 ///////////////////////////////////////////////////////////////////////////
2562 // Type
2563 
2565  // only ReferenceType needs to override this method
2566  return this;
2567 }
2568 
2570  // For many types, this doesn't make any sesne
2571  return NULL;
2572 }
2573 
2574 /** Given an atomic or vector type, return a vector type of the given
2575  vecSize. Issue an error if given a vector type that isn't already that
2576  size.
2577  */
2578 static const Type *lVectorConvert(const Type *type, SourcePos pos, const char *reason, int vecSize) {
2579  const VectorType *vt = CastType<VectorType>(type);
2580  if (vt) {
2581  if (vt->GetElementCount() != vecSize) {
2582  Error(pos,
2583  "Implicit conversion between from vector type "
2584  "\"%s\" to vector type of length %d for %s is not possible.",
2585  type->GetString().c_str(), vecSize, reason);
2586  return NULL;
2587  }
2588  return vt;
2589  } else {
2590  const AtomicType *at = CastType<AtomicType>(type);
2591  if (!at) {
2592  Error(pos,
2593  "Non-atomic type \"%s\" can't be converted to vector type "
2594  "for %s.",
2595  type->GetString().c_str(), reason);
2596  return NULL;
2597  }
2598  return new VectorType(at, vecSize);
2599  }
2600 }
2601 
2602 const Type *Type::MoreGeneralType(const Type *t0, const Type *t1, SourcePos pos, const char *reason, bool forceVarying,
2603  int vecSize) {
2604  Assert(reason != NULL);
2605 
2606  // First, if one or both types are function types, convert them to
2607  // pointer to function types and then try again.
2608  if (CastType<FunctionType>(t0) || CastType<FunctionType>(t1)) {
2609  if (CastType<FunctionType>(t0))
2610  t0 = PointerType::GetUniform(t0);
2611  if (CastType<FunctionType>(t1))
2612  t1 = PointerType::GetUniform(t1);
2613  return MoreGeneralType(t0, t1, pos, reason, forceVarying, vecSize);
2614  }
2615 
2616  // First, if we need to go varying, promote both of the types to be
2617  // varying.
2618  if (t0->IsVaryingType() || t1->IsVaryingType() || forceVarying) {
2619  t0 = t0->GetAsVaryingType();
2620  t1 = t1->GetAsVaryingType();
2621  }
2622 
2623  // And similarly, promote them both to vectors if the caller requested
2624  // a particular vector size
2625  if (vecSize > 0) {
2626  t0 = lVectorConvert(t0, pos, reason, vecSize);
2627  t1 = lVectorConvert(t1, pos, reason, vecSize);
2628  if (!t0 || !t1)
2629  return NULL;
2630  }
2631 
2632  // Are they both the same type? If so, we're done, QED.
2633  if (Type::Equal(t0, t1))
2634  return t0;
2635 
2636  // If they're function types, it's hopeless if they didn't match in the
2637  // Type::Equal() call above. Fail here so that we don't get into
2638  // trouble calling GetAsConstType()...
2639  if (CastType<FunctionType>(t0) || CastType<FunctionType>(t1)) {
2640  Error(pos, "Incompatible function types \"%s\" and \"%s\" in %s.", t0->GetString().c_str(),
2641  t1->GetString().c_str(), reason);
2642  return NULL;
2643  }
2644 
2645  // Not the same types, but only a const/non-const difference? Return
2646  // the non-const type as the more general one.
2647  if (Type::EqualIgnoringConst(t0, t1))
2648  return t0->GetAsNonConstType();
2649 
2650  const PointerType *pt0 = CastType<PointerType>(t0);
2651  const PointerType *pt1 = CastType<PointerType>(t1);
2652  if (pt0 != NULL && pt1 != NULL) {
2653  if (PointerType::IsVoidPointer(pt0))
2654  return pt1;
2655  else if (PointerType::IsVoidPointer(pt1))
2656  return pt0;
2657  else {
2658  Error(pos,
2659  "Conversion between incompatible pointer types \"%s\" "
2660  "and \"%s\" isn't possible.",
2661  t0->GetString().c_str(), t1->GetString().c_str());
2662  return NULL;
2663  }
2664  }
2665 
2666  const VectorType *vt0 = CastType<VectorType>(t0->GetReferenceTarget());
2667  const VectorType *vt1 = CastType<VectorType>(t1->GetReferenceTarget());
2668  if (vt0 && vt1) {
2669  // both are vectors; convert their base types and make a new vector
2670  // type, as long as their lengths match
2671  if (vt0->GetElementCount() != vt1->GetElementCount()) {
2672  Error(pos,
2673  "Implicit conversion between differently sized vector types "
2674  "(%s, %s) for %s is not possible.",
2675  t0->GetString().c_str(), t1->GetString().c_str(), reason);
2676  return NULL;
2677  }
2678  const Type *t = MoreGeneralType(vt0->GetElementType(), vt1->GetElementType(), pos, reason, forceVarying);
2679  if (!t)
2680  return NULL;
2681 
2682  // The 'more general' version of the two vector element types must
2683  // be an AtomicType (that's all that vectors can hold...)
2684  const AtomicType *at = CastType<AtomicType>(t);
2685  Assert(at != NULL);
2686 
2687  return new VectorType(at, vt0->GetElementCount());
2688  } else if (vt0) {
2689  // If one type is a vector type but the other isn't, see if we can
2690  // promote the other one to a vector type. This will fail and
2691  // return NULL if t1 is e.g. an array type and it's illegal to have
2692  // a vector of it..
2693  const Type *t = MoreGeneralType(vt0->GetElementType(), t1, pos, reason, forceVarying);
2694  if (!t)
2695  return NULL;
2696 
2697  const AtomicType *at = CastType<AtomicType>(t);
2698  Assert(at != NULL);
2699  return new VectorType(at, vt0->GetElementCount());
2700  } else if (vt1) {
2701  // As in the above case, see if we can promote t0 to make a vector
2702  // that matches vt1.
2703  const Type *t = MoreGeneralType(t0, vt1->GetElementType(), pos, reason, forceVarying);
2704  if (!t)
2705  return NULL;
2706 
2707  const AtomicType *at = CastType<AtomicType>(t);
2708  Assert(at != NULL);
2709  return new VectorType(at, vt1->GetElementCount());
2710  }
2711 
2712  // TODO: what do we need to do about references here, if anything??
2713 
2714  const AtomicType *at0 = CastType<AtomicType>(t0->GetReferenceTarget());
2715  const AtomicType *at1 = CastType<AtomicType>(t1->GetReferenceTarget());
2716 
2717  const EnumType *et0 = CastType<EnumType>(t0->GetReferenceTarget());
2718  const EnumType *et1 = CastType<EnumType>(t1->GetReferenceTarget());
2719  if (et0 != NULL && et1 != NULL) {
2720  // Two different enum types -> make them uint32s...
2721  Assert(et0->IsVaryingType() == et1->IsVaryingType());
2722  return et0->IsVaryingType() ? AtomicType::VaryingUInt32 : AtomicType::UniformUInt32;
2723  } else if (et0 != NULL) {
2724  if (at1 != NULL)
2725  // Enum type and atomic type -> convert the enum to the atomic type
2726  // TODO: should we return uint32 here, unless the atomic type is
2727  // a 64-bit atomic type, in which case we return that?
2728  return at1;
2729  else {
2730  Error(pos,
2731  "Implicit conversion from enum type \"%s\" to "
2732  "non-atomic type \"%s\" for %s not possible.",
2733  t0->GetString().c_str(), t1->GetString().c_str(), reason);
2734  return NULL;
2735  }
2736  } else if (et1 != NULL) {
2737  if (at0 != NULL)
2738  // Enum type and atomic type; see TODO above here as well...
2739  return at0;
2740  else {
2741  Error(pos,
2742  "Implicit conversion from enum type \"%s\" to "
2743  "non-atomic type \"%s\" for %s not possible.",
2744  t1->GetString().c_str(), t0->GetString().c_str(), reason);
2745  return NULL;
2746  }
2747  }
2748 
2749  // Now all we can do is promote atomic types...
2750  if (at0 == NULL || at1 == NULL) {
2751  Assert(reason != NULL);
2752  Error(pos, "Implicit conversion from type \"%s\" to \"%s\" for %s not possible.", t0->GetString().c_str(),
2753  t1->GetString().c_str(), reason);
2754  return NULL;
2755  }
2756 
2757  // Finally, to determine which of the two atomic types is more general,
2758  // use the ordering of entries in the AtomicType::BasicType enumerator.
2759  return (int(at0->basicType) >= int(at1->basicType)) ? at0 : at1;
2760 }
2761 
2762 bool Type::IsBasicType(const Type *type) {
2763  return (CastType<AtomicType>(type) != NULL || CastType<EnumType>(type) != NULL ||
2764  CastType<PointerType>(type) != NULL);
2765 }
2766 
2767 static bool lCheckTypeEquality(const Type *a, const Type *b, bool ignoreConst) {
2768  if (a == NULL || b == NULL)
2769  return false;
2770 
2771  if (ignoreConst == false && a->IsConstType() != b->IsConstType())
2772  return false;
2773 
2774  const AtomicType *ata = CastType<AtomicType>(a);
2775  const AtomicType *atb = CastType<AtomicType>(b);
2776  if (ata != NULL && atb != NULL) {
2777  return ((ata->basicType == atb->basicType) && (ata->GetVariability() == atb->GetVariability()));
2778  }
2779 
2780  // For all of the other types, we need to see if we have the same two
2781  // general types. If so, then we dig into the details of the type and
2782  // see if all of the relevant bits are equal...
2783  const EnumType *eta = CastType<EnumType>(a);
2784  const EnumType *etb = CastType<EnumType>(b);
2785  if (eta != NULL && etb != NULL)
2786  // Kind of goofy, but this sufficies to check
2787  return (eta->pos == etb->pos && eta->GetVariability() == etb->GetVariability());
2788 
2789  const ArrayType *arta = CastType<ArrayType>(a);
2790  const ArrayType *artb = CastType<ArrayType>(b);
2791  if (arta != NULL && artb != NULL)
2792  return (arta->GetElementCount() == artb->GetElementCount() &&
2793  lCheckTypeEquality(arta->GetElementType(), artb->GetElementType(), ignoreConst));
2794 
2795  const VectorType *vta = CastType<VectorType>(a);
2796  const VectorType *vtb = CastType<VectorType>(b);
2797  if (vta != NULL && vtb != NULL)
2798  return (vta->GetElementCount() == vtb->GetElementCount() &&
2799  lCheckTypeEquality(vta->GetElementType(), vtb->GetElementType(), ignoreConst));
2800 
2801  const StructType *sta = CastType<StructType>(a);
2802  const StructType *stb = CastType<StructType>(b);
2803  const UndefinedStructType *usta = CastType<UndefinedStructType>(a);
2804  const UndefinedStructType *ustb = CastType<UndefinedStructType>(b);
2805  if ((sta != NULL || usta != NULL) && (stb != NULL || ustb != NULL)) {
2806  // Report both defuned and undefined structs as equal if their
2807  // names are the same.
2808  if (a->GetVariability() != b->GetVariability())
2809  return false;
2810 
2811  const std::string &namea = sta ? sta->GetStructName() : usta->GetStructName();
2812  const std::string &nameb = stb ? stb->GetStructName() : ustb->GetStructName();
2813  return (namea == nameb);
2814  }
2815 
2816  const PointerType *pta = CastType<PointerType>(a);
2817  const PointerType *ptb = CastType<PointerType>(b);
2818  if (pta != NULL && ptb != NULL)
2819  return (pta->IsUniformType() == ptb->IsUniformType() && pta->IsSlice() == ptb->IsSlice() &&
2820  pta->IsFrozenSlice() == ptb->IsFrozenSlice() &&
2821  lCheckTypeEquality(pta->GetBaseType(), ptb->GetBaseType(), ignoreConst));
2822 
2823  const ReferenceType *rta = CastType<ReferenceType>(a);
2824  const ReferenceType *rtb = CastType<ReferenceType>(b);
2825  if (rta != NULL && rtb != NULL)
2826  return (lCheckTypeEquality(rta->GetReferenceTarget(), rtb->GetReferenceTarget(), ignoreConst));
2827 
2828  const FunctionType *fta = CastType<FunctionType>(a);
2829  const FunctionType *ftb = CastType<FunctionType>(b);
2830  if (fta != NULL && ftb != NULL) {
2831  // Both the return types and all of the argument types must match
2832  // for function types to match
2833  if (!lCheckTypeEquality(fta->GetReturnType(), ftb->GetReturnType(), ignoreConst))
2834  return false;
2835 
2836  if (fta->isTask != ftb->isTask || fta->isExported != ftb->isExported || fta->isExternC != ftb->isExternC ||
2837  fta->isUnmasked != ftb->isUnmasked)
2838  return false;
2839 
2840  if (fta->GetNumParameters() != ftb->GetNumParameters())
2841  return false;
2842 
2843  for (int i = 0; i < fta->GetNumParameters(); ++i)
2844  if (!lCheckTypeEquality(fta->GetParameterType(i), ftb->GetParameterType(i), ignoreConst))
2845  return false;
2846 
2847  return true;
2848  }
2849 
2850  return false;
2851 }
2852 
2853 bool Type::Equal(const Type *a, const Type *b) { return lCheckTypeEquality(a, b, false); }
2854 
2855 bool Type::EqualIgnoringConst(const Type *a, const Type *b) { return lCheckTypeEquality(a, b, true); }
virtual bool IsIntType() const =0
static const AtomicType * VaryingInt32
Definition: type.h:325
llvm::SmallVector< Expr *, 8 > paramDefaults
Definition: type.h:914
bool IsConstType() const
Definition: type.cpp:1946
static llvm::Type * FloatType
Definition: llvmutil.h:69
virtual const Type * GetAsVaryingType() const =0
const UndefinedStructType * GetAsUnboundVariabilityType() const
Definition: type.cpp:1962
bool IsReferenceType() const
Definition: type.cpp:165
const ArrayType * GetAsVaryingType() const
Definition: type.cpp:1119
const StructType * oppositeConstStructType
Definition: type.h:732
static const AtomicType * VaryingInt16
Definition: type.h:324
bool IsUniformType() const
Definition: type.h:134
static bool lCheckTypeEquality(const Type *a, const Type *b, bool ignoreConst)
Definition: type.cpp:2767
bool IsUnsignedType() const
Definition: type.cpp:1102
bool IsUnsignedType() const
Definition: type.cpp:819
EnumType(SourcePos pos)
Definition: type.cpp:578
bool IsConstType() const
Definition: type.cpp:1651
std::string GetString() const
Definition: type.cpp:302
bool IsIntType() const
Definition: type.cpp:2273
llvm::DIType * GetDIType(llvm::DIScope *scope) const
Definition: type.cpp:1820
const bool isConst
Definition: type.h:776
bool IsUnsignedType() const
Definition: type.cpp:1649
bool IsFloatType() const
Definition: type.cpp:815
Definition: ispc.h:75
llvm::DIFile * GetDIFile() const
Definition: ispc.cpp:1507
std::string Mangle() const
Definition: type.cpp:1787
const Type * GetReturnType() const
Definition: type.h:864
virtual const Type * GetAsUnsignedType() const
Definition: type.cpp:2569
const ReferenceType * GetAsConstType() const
Definition: type.cpp:2140
virtual const Type * ResolveUnboundVariability(Variability v) const =0
static const AtomicType * VaryingUInt64
Definition: type.h:331
static llvm::Type * DoubleType
Definition: llvmutil.h:70
bool IsBoolType() const
Definition: type.cpp:2047
std::string Mangle() const
Definition: type.cpp:2182
const UndefinedStructType * GetAsNonConstType() const
Definition: type.cpp:1985
bool IsVaryingType() const
Definition: type.h:137
const bool isConst
Definition: type.h:337
bool IsSOAType() const
Definition: type.h:141
static PointerType * Void
Definition: type.h:463
const PointerType * GetAsUniformType() const
Definition: type.cpp:832
llvm::Type * LLVMStorageType(llvm::LLVMContext *ctx) const
Definition: type.cpp:1458
bool IsFrozenSlice() const
Definition: type.h:440
bool IsUnsignedType() const
Definition: type.cpp:1944
llvm::DIType * GetDIType(llvm::DIScope *scope) const
Definition: type.cpp:1462
SourcePos Union(const SourcePos &p1, const SourcePos &p2)
Definition: ispc.cpp:1523
std::string GetString() const
Definition: type.cpp:85
Variability GetVariability() const
Definition: type.cpp:2269
llvm::Type * LLVMStorageType(llvm::LLVMContext *ctx) const
Definition: type.cpp:509
int first_line
Definition: ispc.h:127
int GetSOAWidth() const
Definition: type.h:145
const AtomicType * GetAsVaryingType() const
Definition: type.cpp:231
Target * target
Definition: ispc.h:512
std::string Mangle() const
Definition: type.cpp:2001
static llvm::VectorType * VoidPointerVectorType
Definition: llvmutil.h:98
static llvm::VectorType * BoolVectorType
Definition: llvmutil.h:81
const Type * GetAsSOAType(int width) const
Definition: type.cpp:2127
llvm::DIType * GetDIType(llvm::DIScope *scope) const
Definition: type.cpp:2435
const Type * GetBaseType() const
Definition: type.cpp:1948
std::string Mangle() const
Definition: type.cpp:917
const AtomicType * GetAsUnboundVariabilityType() const
Definition: type.cpp:281
static const AtomicType * VaryingDouble
Definition: type.h:332
std::string Mangle() const
Definition: type.cpp:354
const std::string & GetParameterName(int i) const
Definition: type.cpp:2556
const PointerType * GetAsNonConstType() const
Definition: type.cpp:890
llvm::Type * LLVMType(llvm::LLVMContext *ctx) const
Definition: type.cpp:725
Abstract base class for types that represent sequences.
Definition: type.h:498
llvm::ArrayType * LLVMType(llvm::LLVMContext *ctx) const
Definition: type.cpp:1080
std::string GetString() const
Definition: type.cpp:1746
bool IsBoolType() const
Definition: type.cpp:181
int getVectorMemoryCount() const
Definition: type.cpp:1491
std::string GetString() const
Definition: type.cpp:897
std::string GetCDeclaration(const std::string &name) const
Definition: type.cpp:2192
const StructType * GetAsUniformType() const
Definition: type.cpp:1680
static llvm::Type * BoolType
Definition: llvmutil.h:62
bool IsFloatType() const
Definition: type.cpp:1353
std::string GetCDeclaration(const std::string &fname) const
Definition: type.cpp:2364
const Type * GetElementType() const
Definition: type.cpp:1185
const std::string & GetStructName() const
Definition: type.h:704
bool IsDefined() const
Definition: type.cpp:1653
std::string Mangle() const
Definition: type.cpp:2350
static std::string lMangleStruct(Variability variability, bool isConst, const std::string &name)
Definition: type.cpp:1772
static std::string lMangleStructName(const std::string &name, Variability variability)
Definition: type.cpp:1538
Variability variability
Definition: type.h:394
PointerType(const Type *t, Variability v, bool isConst, bool isSlice=false, bool frozen=false)
Definition: type.cpp:794
bool IsBoolType() const
Definition: type.cpp:2275
Variability GetVariability() const
Definition: type.cpp:589
const std::string name
Definition: type.h:393
static llvm::VectorType * Int32VectorType
Definition: llvmutil.h:86
int getMaskBitCount() const
Definition: ispc.h:251
const EnumType * GetAsVaryingType() const
Definition: type.cpp:623
static const AtomicType * UniformUInt32
Definition: type.h:328
int soaWidth
Definition: type.h:68
int GetElementNumber(const std::string &name) const
Definition: type.cpp:1888
llvm::Type * LLVMType(llvm::LLVMContext *ctx) const
Definition: type.cpp:2220
static llvm::VectorType * BoolVectorStorageType
Definition: llvmutil.h:82
bool IsIntType() const
Definition: type.cpp:1355
static PointerType * GetVarying(const Type *t)
Definition: type.cpp:803
llvm::Type * LLVMType(llvm::LLVMContext *ctx) const
Definition: type.cpp:510
const VectorType * GetAsConstType() const
Definition: type.cpp:1389
int getDataTypeWidth() const
Definition: ispc.h:243
Variability GetVariability() const
Definition: type.cpp:159
bool IsIntType() const
Definition: type.cpp:1647
int GetNumParameters() const
Definition: type.h:874
Module * m
Definition: ispc.cpp:73
const Variability variability
Definition: type.h:726
static std::map< std::string, llvm::StructType * > lStructTypeMap
Definition: type.cpp:1529
std::string Mangle() const
Definition: type.cpp:1402
A list of expressions.
Definition: expr.h:249
llvm::DIType * GetDIType(llvm::DIScope *scope) const
Definition: type.cpp:512
Type implementation for pointers to other types.
Definition: type.h:419
const ReferenceType * GetAsUniformType() const
Definition: type.cpp:2107
const int numElements
Definition: type.h:586
static llvm::Type * Int16Type
Definition: llvmutil.h:66
UndefinedStructType(const std::string &name, const Variability variability, bool isConst, SourcePos pos)
Definition: type.cpp:1925
const Type * GetBaseType() const
Definition: type.cpp:2089
llvm::DIType * GetDIType(llvm::DIScope *scope) const
Definition: type.cpp:1040
int TotalElementCount() const
Definition: type.cpp:1266
const StructType * GetAsVaryingType() const
Definition: type.cpp:1672
bool IsConstType() const
Definition: type.cpp:183
const UndefinedStructType * GetAsUniformType() const
Definition: type.cpp:1956
const Variability variability
Definition: type.h:775
const llvm::SmallVector< std::string, 8 > paramNames
Definition: type.h:911
const PointerType * ResolveUnboundVariability(Variability v) const
Definition: type.cpp:871
static llvm::Type * lGetAtomicLLVMType(llvm::LLVMContext *ctx, const AtomicType *aType, bool isStorageType)
Definition: type.cpp:467
static const AtomicType * UniformUInt16
Definition: type.h:327
static PointerType * GetUniform(const Type *t, bool isSlice=false)
Definition: type.cpp:799
std::string MangleString() const
Definition: type.cpp:104
const Type * GetBaseType() const
Definition: type.cpp:1363
bool IsFloatType() const
Definition: type.cpp:1098
const VectorType * ResolveUnboundVariability(Variability v) const
Definition: type.cpp:1377
bool IsBoolType() const
Definition: type.cpp:1104
llvm::DIType * GetDIType(llvm::DIScope *scope) const
Definition: type.cpp:743
std::string GetString() const
Definition: type.cpp:673
virtual llvm::Type * LLVMType(llvm::LLVMContext *ctx) const =0
header file with declarations for symbol and symbol table classes.
static const AtomicType * UniformBool
Definition: type.h:322
const StructType * GetAsSOAType(int width) const
Definition: type.cpp:1696
const Type * GetAsVaryingType() const
Definition: type.cpp:2286
int costOverride
Definition: type.h:903
Type representing a reference to another (non-reference) type.
Definition: type.h:782
bool IsBoolType() const
Definition: type.cpp:591
virtual const Type * GetReferenceTarget() const
Definition: type.cpp:2564
virtual llvm::DIType * GetDIType(llvm::DIScope *scope) const =0
const AtomicType * GetAsUnsignedType() const
Definition: type.cpp:185
const Type * baseType
Definition: type.h:469
std::string GetString() const
Definition: type.cpp:2170
llvm::Module * module
Definition: module.h:151
const PointerType * GetAsSOAType(int width) const
Definition: type.cpp:846
VectorType(const AtomicType *base, int size)
Definition: type.cpp:1346
static bool IsVoidPointer(const Type *t)
Definition: type.cpp:807
Expr * GetParameterDefault(int i) const
Definition: type.cpp:2546
bool IsIntType() const
Definition: type.cpp:595
llvm::Type * LLVMType(llvm::LLVMContext *ctx) const
Definition: type.cpp:1809
const llvm::SmallVector< std::string, 8 > elementNames
Definition: type.h:722
std::vector< Symbol * > enumerators
Definition: type.h:396
const VectorType * GetAsUniformType() const
Definition: type.cpp:1367
Variability GetVariability() const
Definition: type.cpp:2039
static const AtomicType * UniformUInt64
Definition: type.h:331
const StructType * ResolveUnboundVariability(Variability v) const
Definition: type.cpp:1707
const SourcePos & GetParameterSourcePos(int i) const
Definition: type.cpp:2551
const StructType * GetAsUnboundVariabilityType() const
Definition: type.cpp:1688
static llvm::VectorType * Int8VectorType
Definition: llvmutil.h:84
bool IsSlice() const
Definition: type.h:439
const VectorType * GetAsVaryingType() const
Definition: type.cpp:1365
AtomicType(BasicType basicType, Variability v, bool isConst)
Definition: type.cpp:153
const bool isExternC
Definition: type.h:890
std::string Mangle() const
Definition: type.cpp:1211
bool IsConstType() const
Definition: type.cpp:1106
const llvm::SmallVector< SourcePos, 8 > elementPositions
Definition: type.h:725
llvm::SmallVector< const Type *, 8 > finalElementTypes
Definition: type.h:730
Definition: type.h:75
const ReferenceType * GetAsNonConstType() const
Definition: type.cpp:2155
static bool checkIfCanBeSOA(const StructType *st)
Definition: type.cpp:1895
bool IsUnsignedType() const
Definition: type.cpp:176
const FunctionType * ResolveUnboundVariability(Variability v) const
Definition: type.cpp:2306
std::string GetCDeclaration(const std::string &name) const
Definition: type.cpp:2003
static llvm::VectorType * FloatVectorType
Definition: llvmutil.h:88
const Type * GetReferenceTarget() const
Definition: type.cpp:2087
std::string GetCDeclaration(const std::string &name) const
Definition: type.cpp:1409
bool IsFloatType() const
Definition: type.cpp:1645
std::string Mangle() const
Definition: type.cpp:685
const EnumType * ResolveUnboundVariability(Variability v) const
Definition: type.cpp:613
bool IsConstType() const
Definition: type.cpp:821
virtual bool IsBoolType() const =0
Variability GetVariability() const
Definition: type.cpp:1936
const AtomicType * GetAsSOAType(int width) const
Definition: type.cpp:288
static llvm::Type * Int64Type
Definition: llvmutil.h:68
const SourcePos pos
Definition: type.h:390
static llvm::Type * Int8Type
Definition: llvmutil.h:65
static const Type * MoreGeneralType(const Type *type0, const Type *type1, SourcePos pos, const char *reason, bool forceVarying=false, int vecSize=0)
Definition: type.cpp:2602
Representation of a structure holding a number of members.
Definition: type.h:650
const Type * GetAsSOAType(int width) const
Definition: type.cpp:2301
const ArrayType * ResolveUnboundVariability(Variability v) const
Definition: type.cpp:1151
const EnumType * GetAsUnboundVariabilityType() const
Definition: type.cpp:633
const VectorType * GetAsSOAType(int width) const
Definition: type.cpp:1373
static llvm::VectorType * Int64VectorType
Definition: llvmutil.h:87
Header file with declarations for various LLVM utility stuff.
const UndefinedStructType * ResolveUnboundVariability(Variability v) const
Definition: type.cpp:1973
virtual bool IsFloatType() const =0
Variability GetVariability() const
Definition: type.cpp:1641
const ReferenceType * GetAsUnboundVariabilityType() const
Definition: type.cpp:2117
const ReferenceType * GetAsVaryingType() const
Definition: type.cpp:2097
const EnumType * GetAsSOAType(int width) const
Definition: type.cpp:643
const AtomicType *const base
Definition: type.h:637
const Type * GetAsUniformType() const
Definition: type.cpp:2291
const AtomicType * GetAsConstType() const
Definition: type.cpp:207
const Type * GetBaseType() const
Definition: type.cpp:1108
std::string GetCDeclaration(const std::string &name) const
Definition: type.cpp:403
const AtomicType * asVaryingType
Definition: type.h:340
static bool IsBasicType(const Type *type)
Definition: type.cpp:2762
bool IsBoolType() const
Definition: type.cpp:1938
std::string name
Definition: type.h:710
AtomicType represents basic types like floats, ints, etc.
Definition: type.h:270
static llvm::Type * lGetVectorLLVMType(llvm::LLVMContext *ctx, const VectorType *vType, bool isStorage)
Definition: type.cpp:1420
bool IsFloatType() const
Definition: type.cpp:2055
const Type *const returnType
Definition: type.h:906
bool IsIntType() const
Definition: type.cpp:2063
const Type * GetAsUnboundVariabilityType() const
Definition: type.cpp:2296
const ArrayType * GetAsUnboundVariabilityType() const
Definition: type.cpp:1135
const bool isConst
Definition: type.h:467
Representation of a range of positions in a source file.
Definition: ispc.h:123
virtual std::string Mangle() const =0
const EnumType * GetAsNonConstType() const
Definition: type.cpp:663
bool IsBoolType() const
Definition: type.cpp:1359
Type implementation for enumerated types.
Definition: type.h:347
virtual const Type * GetAsNonConstType() const =0
const Type * GetAsConstType() const
Definition: type.cpp:2330
static const AtomicType * VaryingBool
Definition: type.h:322
virtual std::string GetString() const =0
std::string GetCDeclaration(const std::string &name) const
Definition: type.cpp:697
Abstract base class for types that represent collections of other types.
Definition: type.h:478
bool IsIntType() const
Definition: type.cpp:817
int GetElementCount() const
Definition: type.h:699
llvm::Type * LLVMType(llvm::LLVMContext *ctx) const
Definition: type.cpp:2013
bool IsFloatType() const
Definition: type.cpp:593
const PointerType * GetAsVaryingType() const
Definition: type.cpp:825
ArrayType(const Type *elementType, int numElements)
Definition: type.cpp:1074
bool IsConstType() const
Definition: type.cpp:599
const AtomicType * asOtherConstType
Definition: type.h:340
void SetEnumerators(const std::vector< Symbol *> &enumerators)
Definition: type.cpp:783
const ArrayType * GetAsUnsignedType() const
Definition: type.cpp:1159
bool isConst
Definition: type.h:395
const ArrayType * GetAsNonConstType() const
Definition: type.cpp:1175
bool IsUnsignedType() const
Definition: type.cpp:597
const BasicType basicType
Definition: type.h:320
llvm::DIType * GetDIType(llvm::DIScope *scope) const
Definition: type.cpp:2023
bool IsVoidType() const
Definition: type.cpp:167
static llvm::PointerType * VoidPointerType
Definition: llvmutil.h:60
const Type *const targetType
Definition: type.h:814
static const AtomicType * VaryingInt64
Definition: type.h:330
void Error(SourcePos p, const char *fmt,...)
Definition: util.cpp:351
const Type * GetAsNonConstType() const
Definition: type.cpp:2332
int GetEnumeratorCount() const
Definition: type.cpp:785
std::string GetCDeclaration(const std::string &name) const
Definition: type.cpp:1226
int getVectorWidth() const
Definition: ispc.h:245
std::string GetString() const
Definition: type.cpp:1187
const PointerType * GetAsSlice() const
Definition: type.cpp:853
const SourcePos pos
Definition: type.h:728
virtual const Type * GetAsSOAType(int width) const =0
const StructType * GetAsConstType() const
Definition: type.cpp:1720
ReferenceType(const Type *targetType)
Definition: type.cpp:2037
bool IsPointerType() const
Definition: type.cpp:161
#define FATAL(message)
Definition: util.h:116
const int numElements
Definition: type.h:639
const AtomicType * GetElementType() const
Definition: type.cpp:1418
const AtomicType * GetBaseType() const
Definition: type.cpp:229
Variability GetVariability() const
Definition: type.cpp:1351
bool IsUnsignedType() const
Definition: type.cpp:1357
const llvm::SmallVector< const Type *, 8 > elementTypes
Definition: type.h:721
const Variability variability
Definition: type.h:336
A (short) vector of atomic types.
Definition: type.h:600
llvm::Type * LLVMType(llvm::LLVMContext *ctx) const
Definition: type.cpp:1460
bool IsConstType() const
Definition: type.cpp:2279
const Type * GetBaseType() const
Definition: type.cpp:2281
static const AtomicType * UniformUInt8
Definition: type.h:326
static const Type * lVectorConvert(const Type *type, SourcePos pos, const char *reason, int vecSize)
Definition: type.cpp:2578
const VectorType * GetAsUnsignedType() const
Definition: type.cpp:1381
const Type * GetElementType(const std::string &name) const
Definition: type.cpp:1881
static llvm::Type * Int32Type
Definition: llvmutil.h:67
const llvm::DataLayout * getDataLayout() const
Definition: ispc.h:224
const std::string GetCStructName() const
Definition: type.cpp:1630
virtual const Type * GetAsUniformType() const =0
const UndefinedStructType * GetAsSOAType(int width) const
Definition: type.cpp:1968
const EnumType * GetBaseType() const
Definition: type.cpp:601
const EnumType * GetAsConstType() const
Definition: type.cpp:653
std::string GetString() const
Definition: type.cpp:1991
const ArrayType * GetAsConstType() const
Definition: type.cpp:1167
static llvm::DIType * lCreateDIArray(llvm::DIType *eltType, int count)
Definition: type.cpp:70
const ArrayType * GetAsSOAType(int width) const
Definition: type.cpp:1143
static llvm::Type * BoolStorageType
Definition: llvmutil.h:63
const bool isSlice
Definition: type.h:468
const PointerType * GetAsUnboundVariabilityType() const
Definition: type.cpp:839
const llvm::SmallVector< SourcePos, 8 > paramPositions
Definition: type.h:919
std::string GetCDeclarationForDispatch(const std::string &fname) const
Definition: type.cpp:2392
#define Assert(expr)
Definition: util.h:128
static bool Equal(const Type *a, const Type *b)
Definition: type.cpp:2853
virtual const Type * GetElementType() const =0
static const AtomicType * VaryingUInt16
Definition: type.h:327
const bool isTask
Definition: type.h:882
std::vector< Expr * > exprs
Definition: expr.h:266
const Type *const child
Definition: type.h:584
static const AtomicType * UniformFloat
Definition: type.h:329
static const AtomicType * VaryingInt8
Definition: type.h:323
const PointerType * GetAsFrozenSlice() const
Definition: type.cpp:865
llvm::DIType * GetDIType(llvm::DIScope *scope) const
Definition: type.cpp:1274
virtual bool IsUnsignedType() const =0
BasicType
Definition: type.h:304
llvm::DIType * GetDIType(llvm::DIScope *scope) const
Definition: type.cpp:2235
const Type * GetParameterType(int i) const
Definition: type.cpp:2541
static const AtomicType * UniformInt32
Definition: type.h:325
const Symbol * GetEnumerator(int i) const
Definition: type.cpp:787
Type representing a function (return type + argument types)
Definition: type.h:829
Representation of a program symbol.
Definition: sym.h:62
const PointerType * GetAsNonSlice() const
Definition: type.cpp:859
const VectorType * GetAsUnboundVariabilityType() const
Definition: type.cpp:1369
const llvm::SmallVector< const Type *, 8 > paramTypes
Definition: type.h:910
virtual bool IsConstType() const =0
Interface class that defines the type abstraction.
Definition: type.h:90
static const AtomicType * UniformDouble
Definition: type.h:332
const Type * GetBaseType() const
Definition: type.cpp:1670
const UndefinedStructType * GetAsConstType() const
Definition: type.cpp:1979
Globals * g
Definition: ispc.cpp:72
const bool isFrozen
Definition: type.h:468
bool IsFloatType() const
Definition: type.cpp:169
virtual Variability GetVariability() const =0
Expr abstract base class and expression implementations.
static const AtomicType * Void
Definition: type.h:333
virtual const Type * GetAsConstType() const =0
const StructType * GetAsNonConstType() const
Definition: type.cpp:1733
static llvm::VectorType * MaskType
Definition: llvmutil.h:79
const bool isUnmasked
Definition: type.h:895
const SourcePos pos
Definition: type.h:777
const ReferenceType * ResolveUnboundVariability(Variability v) const
Definition: type.cpp:2132
llvm::Type * LLVMType(llvm::LLVMContext *ctx) const
Definition: type.cpp:983
const AtomicType * asUniformType
Definition: type.h:340
bool IsConstType() const
Definition: type.cpp:2079
StructType(const std::string &name, const llvm::SmallVector< const Type *, 8 > &elts, const llvm::SmallVector< std::string, 8 > &eltNames, const llvm::SmallVector< SourcePos, 8 > &eltPositions, bool isConst, Variability variability, SourcePos pos)
Definition: type.cpp:1568
bool IsUnsignedType() const
Definition: type.cpp:2071
int GetElementCount() const
Definition: type.cpp:1183
Expr is the abstract base class that defines the interface that all expression types must implement...
Definition: expr.h:47
bool IsIntType() const
Definition: type.cpp:1942
static llvm::VectorType * DoubleVectorType
Definition: llvmutil.h:89
bool IsUnsignedType() const
Definition: type.cpp:2277
virtual std::string GetCDeclaration(const std::string &name) const =0
bool IsFloatType() const
Definition: type.cpp:1940
std::string GetString() const
Definition: type.cpp:1395
static const Type * SizeUnsizedArrays(const Type *type, Expr *initExpr)
Definition: type.cpp:1288
virtual const Type * GetBaseType() const =0
VarType type
Definition: type.h:67
virtual ArrayType * GetSizedArray(int length) const
Definition: type.cpp:1283
std::string GetCDeclaration(const std::string &name) const
Definition: type.cpp:1789
static llvm::VectorType * Int16VectorType
Definition: llvmutil.h:85
llvm::Type * LLVMType(llvm::LLVMContext *ctx) const
Definition: type.cpp:2430
static bool lShouldPrintName(const std::string &name)
Definition: type.cpp:59
const AtomicType * GetAsUniformType() const
Definition: type.cpp:244
const ArrayType * GetAsUniformType() const
Definition: type.cpp:1127
const PointerType * GetAsConstType() const
Definition: type.cpp:883
bool IsConstType() const
Definition: type.cpp:1361
const std::string name
Definition: type.h:774
bool isSafe
Definition: type.h:899
Variability GetVariability() const
Definition: type.cpp:811
std::string GetCDeclaration(const std::string &name) const
Definition: type.cpp:936
const AtomicType * ResolveUnboundVariability(Variability v) const
Definition: type.cpp:295
const bool isExported
Definition: type.h:886
static const AtomicType * VaryingUInt8
Definition: type.h:326
bool is32Bit() const
Definition: ispc.h:235
const Type * GetBaseType() const
Definition: type.cpp:823
int GetElementCount() const
Definition: type.cpp:1416
bool IsIntType() const
Definition: type.cpp:171
FunctionType(const Type *returnType, const llvm::SmallVector< const Type *, 8 > &argTypes, SourcePos pos)
Definition: type.cpp:2247
Declaration of the Module class, which is the ispc-side representation of the results of compiling a ...
const VectorType * GetAsNonConstType() const
Definition: type.cpp:1391
static const AtomicType * UniformInt64
Definition: type.h:330
int errorCount
Definition: module.h:144
virtual const Type * GetAsUnboundVariabilityType() const =0
llvm::LLVMContext * ctx
Definition: ispc.h:611
static const AtomicType * UniformInt16
Definition: type.h:324
const EnumType * GetAsUniformType() const
Definition: type.cpp:603
llvm::DIBuilder * diBuilder
Definition: module.h:154
bool IsIntType() const
Definition: type.cpp:1100
bool IsFloatType() const
Definition: type.cpp:2271
std::string GetString() const
Definition: type.cpp:2334
static bool EqualIgnoringConst(const Type *a, const Type *b)
Definition: type.cpp:2855
const ReferenceType * asOtherConstType
Definition: type.h:815
bool IsBoolType() const
Definition: type.cpp:813
static const AtomicType * VaryingUInt32
Definition: type.h:328
const AtomicType * GetAsNonConstType() const
Definition: type.cpp:218
const UndefinedStructType * GetAsVaryingType() const
Definition: type.cpp:1950
static const AtomicType * VaryingFloat
Definition: type.h:329
const std::string GetReturnTypeString() const
Definition: type.cpp:2452
virtual llvm::Type * LLVMStorageType(llvm::LLVMContext *ctx) const
Definition: type.cpp:125
static const AtomicType * UniformInt8
Definition: type.h:323
bool HasUnboundVariability() const
Definition: type.h:149
bool IsArrayType() const
Definition: type.cpp:163
File with declarations for classes related to type representation.
Variability GetVariability() const
Definition: type.cpp:1094
llvm::FunctionType * LLVMFunctionType(llvm::LLVMContext *ctx, bool disableMask=false) const
Definition: type.cpp:2476
bool IsBoolType() const
Definition: type.cpp:1643
const bool isConst
Definition: type.h:727
One-dimensional array type.
Definition: type.h:521
const Variability variability
Definition: type.h:466