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