1 ///////////////////////////////////////////////////////////////////////////
2 // Copyright (c) 2013 Academy of Motion Picture Arts and Sciences
3 // ("A.M.P.A.S."). Portions contributed by others as indicated.
4 // All rights reserved.
5 //
6 // A worldwide, royalty-free, non-exclusive right to copy, modify, create
7 // derivatives, and use, in source and binary forms, is hereby granted,
8 // subject to acceptance of this license. Performance of any of the
9 // aforementioned acts indicates acceptance to be bound by the following
10 // terms and conditions:
11 //
12 //  * Copies of source code, in whole or in part, must retain the
13 //    above copyright notice, this list of conditions and the
14 //    Disclaimer of Warranty.
15 //
16 //  * Use in binary form must retain the above copyright notice,
17 //    this list of conditions and the Disclaimer of Warranty in the
18 //    documentation and/or other materials provided with the distribution.
19 //
20 //  * Nothing in this license shall be deemed to grant any rights to
21 //    trademarks, copyrights, patents, trade secrets or any other
22 //    intellectual property of A.M.P.A.S. or any contributors, except
23 //    as expressly stated herein.
24 //
25 //  * Neither the name "A.M.P.A.S." nor the name of any other
26 //    contributors to this software may be used to endorse or promote
27 //    products derivative of or based on this software without express
28 //    prior written permission of A.M.P.A.S. or the contributors, as
29 //    appropriate.
30 //
31 // This license shall be construed pursuant to the laws of the State of
32 // California, and any disputes related thereto shall be subject to the
33 // jurisdiction of the courts therein.
34 //
35 // Disclaimer of Warranty: THIS SOFTWARE IS PROVIDED BY A.M.P.A.S. AND
36 // CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
37 // BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
38 // FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT ARE DISCLAIMED. IN NO
39 // EVENT SHALL A.M.P.A.S., OR ANY CONTRIBUTORS OR DISTRIBUTORS, BE LIABLE
40 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, RESITUTIONARY,
41 // OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
42 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
43 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
44 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
45 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
46 // THE POSSIBILITY OF SUCH DAMAGE.
47 //
48 // WITHOUT LIMITING THE GENERALITY OF THE FOREGOING, THE ACADEMY
49 // SPECIFICALLY DISCLAIMS ANY REPRESENTATIONS OR WARRANTIES WHATSOEVER
50 // RELATED TO PATENT OR OTHER INTELLECTUAL PROPERTY RIGHTS IN THE ACADEMY
51 // COLOR ENCODING SYSTEM, OR APPLICATIONS THEREOF, HELD BY PARTIES OTHER
52 // THAN A.M.P.A.S., WHETHER DISCLOSED OR UNDISCLOSED.
53 ///////////////////////////////////////////////////////////////////////////
54 
55 //-----------------------------------------------------------------------------
56 //
57 //	Types in the SIMD implementation of the color transformation language
58 //
59 //-----------------------------------------------------------------------------
60 
61 #include <CtlSimdType.h>
62 #include <CtlSyntaxTree.h>
63 #include <CtlSymbolTable.h>
64 #include <CtlSimdLContext.h>
65 #include <CtlSimdModule.h>
66 #include <CtlSimdInst.h>
67 #include <CtlSimdOp.h>
68 #include <CtlAlign.h>
69 #include <CtlMessage.h>
70 #include <cassert>
71 #include <CtlErrors.h>
72 
73 using namespace std;
74 
75 namespace Ctl {
76 namespace {
77 
78 bool
isAssignment(const SyntaxNodePtr & node)79 isAssignment (const SyntaxNodePtr &node)
80 {
81     return node.cast<AssignmentNode>() ||
82 	   node.cast<VariableNode>() ||
83 	   node.cast<ReturnNode>();
84 }
85 
86 } // namespace
87 
88 
SimdVoidType()89 SimdVoidType::SimdVoidType(): VoidType ()
90 {
91     // empty
92 }
93 
94 
95 size_t
objectSize() const96 SimdVoidType::objectSize () const
97 {
98     return 0;
99 }
100 
101 
102 size_t
alignedObjectSize() const103 SimdVoidType::alignedObjectSize () const
104 {
105     return 0;
106 }
107 
108 
109 size_t
objectAlignment() const110 SimdVoidType::objectAlignment () const
111 {
112     return 1;
113 }
114 
115 
116 void
generateCastFrom(const ExprNodePtr & expr,LContext & lcontext) const117 SimdVoidType::generateCastFrom
118     (const ExprNodePtr &expr,
119      LContext &lcontext) const
120 {
121     return;
122 }
123 
124 
125 void
generateCode(const SyntaxNodePtr & node,LContext & lcontext) const126 SimdVoidType::generateCode
127     (const SyntaxNodePtr &node,
128      LContext &lcontext) const
129 {
130 }
131 
132 
SimdBoolType()133 SimdBoolType::SimdBoolType (): BoolType ()
134 {
135     // empty
136 }
137 
138 
139 size_t
objectSize() const140 SimdBoolType::objectSize () const
141 {
142     return sizeof (bool);
143 }
144 
145 
146 size_t
alignedObjectSize() const147 SimdBoolType::alignedObjectSize () const
148 {
149     return sizeof (bool);
150 }
151 
152 
153 size_t
objectAlignment() const154 SimdBoolType::objectAlignment () const
155 {
156     return sizeof (bool);
157 }
158 
159 
160 void
generateCastFrom(const ExprNodePtr & expr,LContext & lcontext) const161 SimdBoolType::generateCastFrom
162     (const ExprNodePtr &expr,
163      LContext &lcontext) const
164 {
165     SimdLContext &slcontext = static_cast <SimdLContext &> (lcontext);
166 
167     if (expr->type.cast<BoolType>())
168     {
169 	return;
170     }
171 
172     if (expr->type.cast<IntType>())
173     {
174 	slcontext.addInst (new SimdUnaryOpInst <int, bool, CopyOp>
175 			   (expr->lineNumber));
176 	return;
177     }
178 
179     if (expr->type.cast<UIntType>())
180     {
181 	slcontext.addInst (new SimdUnaryOpInst <unsigned, bool, CopyOp>
182 			   (expr->lineNumber));
183 	return;
184     }
185 
186     if (expr->type.cast<HalfType>())
187     {
188 	slcontext.addInst (new SimdUnaryOpInst <half, bool, CopyOp>
189 			   (expr->lineNumber));
190 	return;
191     }
192 
193     if (expr->type.cast<FloatType>())
194     {
195 	slcontext.addInst (new SimdUnaryOpInst <float, bool, CopyOp>
196 			   (expr->lineNumber));
197 	return;
198     }
199 
200     MESSAGE_LE (lcontext, ERR_TYPE, expr->lineNumber,
201 		"Cannot cast value of type " << expr->type->asString() <<
202 		" to type " << asString() << ".");
203 }
204 
205 
206 void
generateCode(const SyntaxNodePtr & node,LContext & lcontext) const207 SimdBoolType::generateCode
208     (const SyntaxNodePtr &node,
209      LContext &lcontext) const
210 {
211     SimdLContext &slcontext = static_cast <SimdLContext &> (lcontext);
212 
213     if (isAssignment (node))
214     {
215 	slcontext.addInst
216 	    (new SimdAssignInst (alignedObjectSize(), node->lineNumber));
217 	return;
218     }
219 
220     if (UnaryOpNodePtr unOp = node.cast<UnaryOpNode>())
221     {
222 	switch (unOp->op)
223 	{
224 	  case TK_BITNOT:
225 
226 	    //
227 	    // We use the C++ ! operation to evaluate the CTL expression ~x,
228 	    // where x is of type bool.  This ensures that ~true == false
229 	    // and ~false == true.
230 	    //
231 
232 	    slcontext.addInst
233 		(new SimdUnaryOpInst <bool, bool, NotOp>(node->lineNumber));
234 	    break;
235 
236 	  case TK_NOT:
237 	    slcontext.addInst
238 		(new SimdUnaryOpInst <bool, bool, NotOp>(node->lineNumber));
239 	    break;
240 
241 	  default:
242 
243 	    MESSAGE_LE (lcontext, ERR_OP_TYPE, node->lineNumber,
244 		"Cannot apply " << tokenAsString (unOp->op) << " "
245 		"operator to value of type " <<
246 		unOp->operand->type->asString() << ".");
247 	}
248 
249 	return;
250     }
251 
252     if (BinaryOpNodePtr binOp = node.cast<BinaryOpNode>())
253     {
254 	switch (binOp->op)
255 	{
256 	  case TK_BITAND:
257 
258 	    //
259 	    // For the bit-wise &, | and ^ operators, we normalize bool
260 	    // operands before applying the operators.  This avoids
261 	    // surprises, for example, true^true == true.
262 	    //
263 
264 	    slcontext.addInst
265 		(new SimdBinaryOpInst <bool, bool, bool, BoolBitAndOp>
266 		 (node->lineNumber));
267 	    break;
268 
269 	  case TK_BITOR:
270 	    slcontext.addInst
271 		(new SimdBinaryOpInst <bool, bool, bool, BoolBitOrOp>
272 		 (node->lineNumber));
273 	    break;
274 
275 	  case TK_BITXOR:
276 	    slcontext.addInst
277 		(new SimdBinaryOpInst <bool, bool, bool, BoolBitXorOp>
278 		 (node->lineNumber));
279 	    break;
280 
281 	  case TK_EQUAL:
282 	    slcontext.addInst
283 		(new SimdBinaryOpInst <bool, bool, bool, EqualOp>
284 		 (node->lineNumber));
285 	    break;
286 
287 	  case TK_GREATER:
288 	    slcontext.addInst
289 		(new SimdBinaryOpInst <bool, bool, bool, GreaterOp>
290 		 (node->lineNumber));
291 	    break;
292 
293 	  case TK_GREATEREQUAL:
294 	    slcontext.addInst
295 		(new SimdBinaryOpInst <bool, bool, bool, GreaterEqualOp>
296 		 (node->lineNumber));
297 	    break;
298 
299 	  case TK_LESS:
300 	    slcontext.addInst
301 		(new SimdBinaryOpInst <bool, bool, bool, LessOp>
302 		 (node->lineNumber));
303 	    break;
304 
305 	  case TK_LESSEQUAL:
306 	    slcontext.addInst
307 		(new SimdBinaryOpInst <bool, bool, bool, LessEqualOp>
308 		 (node->lineNumber));
309 	    break;
310 
311 	  case TK_NOTEQUAL:
312 	    slcontext.addInst
313 		(new SimdBinaryOpInst <bool, bool, bool, NotEqualOp>
314 		 (node->lineNumber));
315 	    break;
316 
317 	  default:
318 
319 	    MESSAGE_LE (lcontext, ERR_OP_TYPE, node->lineNumber,
320 		"Invalid operand types "
321 		"for " << tokenAsString (binOp->op) << " operator "
322 		"(" << binOp->leftOperand->type->asString() << " " <<
323 		tokenAsString (binOp->op) << " " <<
324 		binOp->rightOperand->type->asString() << ").");
325 	}
326 
327 	return;
328     }
329 
330     if (node.cast<CallNode>())
331     {
332 	//
333 	// Push a placeholder for the return value for a call to
334 	// a function that returns an int.
335 	//
336 	slcontext.addInst (new SimdPushPlaceholderInst(alignedObjectSize(),
337 						       node->lineNumber));
338 	return;
339     }
340 }
341 
342 AddrPtr
newStaticVariableGeneric(Module * module,size_t objectSize)343 newStaticVariableGeneric(Module *module, size_t objectSize)
344 {
345     SimdModule *smodule = static_cast <SimdModule *> (module);
346     SimdReg* reg = new SimdReg (false, objectSize);
347 
348     smodule->addStaticData (reg);
349     return new SimdDataAddr (reg);
350 }
351 
352 
353 AddrPtr
newStaticVariable(Module * module) const354 SimdBoolType::newStaticVariable (Module *module) const
355 {
356     return newStaticVariableGeneric(module, objectSize());
357 }
358 
359 void
newAutomaticVariable(StatementNodePtr node,LContext & lcontext) const360 SimdBoolType::newAutomaticVariable (StatementNodePtr node,
361 				    LContext &lcontext) const
362 {
363     SimdLContext &slcontext = static_cast <SimdLContext &> (lcontext);
364     slcontext.addInst (new SimdPushPlaceholderInst
365 		       (objectSize(), node->lineNumber));
366 }
367 
368 
SimdIntType()369 SimdIntType::SimdIntType (): IntType ()
370 {
371     // empty
372 }
373 
374 
375 size_t
objectSize() const376 SimdIntType::objectSize () const
377 {
378     return sizeof (int);
379 }
380 
381 
382 size_t
alignedObjectSize() const383 SimdIntType::alignedObjectSize () const
384 {
385     return sizeof (int);
386 }
387 
388 
389 size_t
objectAlignment() const390 SimdIntType::objectAlignment () const
391 {
392     return sizeof (int);
393 }
394 
395 
396 void
generateCastFrom(const ExprNodePtr & expr,LContext & lcontext) const397 SimdIntType::generateCastFrom
398     (const ExprNodePtr &expr,
399      LContext &lcontext) const
400 {
401     SimdLContext &slcontext = static_cast <SimdLContext &> (lcontext);
402 
403     if (expr->type.cast<BoolType>())
404     {
405 	slcontext.addInst (new SimdUnaryOpInst <bool, int, CopyOp>
406 			   (expr->lineNumber));
407 	return;
408     }
409 
410     if (expr->type.cast<IntType>())
411     {
412 	return;
413     }
414 
415     if (expr->type.cast<UIntType>())
416     {
417 	slcontext.addInst (new SimdUnaryOpInst <unsigned, int, CopyOp>
418 			   (expr->lineNumber));
419 	return;
420     }
421 
422     if (expr->type.cast<HalfType>())
423     {
424 	slcontext.addInst (new SimdUnaryOpInst <half, int, CopyOp>
425 			   (expr->lineNumber));
426 	return;
427     }
428 
429     if (expr->type.cast<FloatType>())
430     {
431 	slcontext.addInst (new SimdUnaryOpInst <float, int, CopyOp>
432 			   (expr->lineNumber));
433 	return;
434     }
435 
436     MESSAGE_LE (lcontext, ERR_TYPE, expr->lineNumber,
437 		"Cannot cast value of type " << expr->type->asString() <<
438 		" to type " << asString() << ".");
439 }
440 
441 
442 void
generateCode(const SyntaxNodePtr & node,LContext & lcontext) const443 SimdIntType::generateCode
444     (const SyntaxNodePtr &node,
445      LContext &lcontext) const
446 {
447     SimdLContext &slcontext = static_cast <SimdLContext &> (lcontext);
448 
449     if (isAssignment (node))
450     {
451 	slcontext.addInst
452 	    (new SimdAssignInst (alignedObjectSize(), node->lineNumber));
453 	return;
454     }
455 
456     if (UnaryOpNodePtr unOp = node.cast<UnaryOpNode>())
457     {
458 	switch (unOp->op)
459 	{
460 	  case TK_BITNOT:
461 	    slcontext.addInst
462 		(new SimdUnaryOpInst <int, int, BitNotOp>(node->lineNumber));
463 	    break;
464 
465 	  case TK_MINUS:
466 	    slcontext.addInst
467 		(new SimdUnaryOpInst <int, int, UnaryMinusOp>
468 		 (node->lineNumber));
469 	    break;
470 
471 	  default:
472 
473 	    MESSAGE_LE (lcontext, ERR_OP_TYPE, node->lineNumber,
474 		"Cannot apply " << tokenAsString (unOp->op) << " "
475 		"operator to value of type " <<
476 		unOp->operand->type->asString() << ".");
477 	}
478 
479 	return;
480     }
481 
482     if (BinaryOpNodePtr binOp = node.cast<BinaryOpNode>())
483     {
484 	switch (binOp->op)
485 	{
486 	  case TK_BITAND:
487 	    slcontext.addInst
488 		(new SimdBinaryOpInst <int, int, int, BitAndOp>
489 		 (node->lineNumber));
490 	    break;
491 
492 	  case TK_BITOR:
493 	    slcontext.addInst
494 		(new SimdBinaryOpInst <int, int, int, BitOrOp>
495 		 (node->lineNumber));
496 	    break;
497 
498 	  case TK_BITXOR:
499 	    slcontext.addInst
500 		(new SimdBinaryOpInst <int, int, int, BitXorOp>
501 		 (node->lineNumber));
502 	    break;
503 
504 	  case TK_DIV:
505 	    slcontext.addInst
506 		(new SimdBinaryOpInst <int, int, int, IntDivOp>
507 		 (node->lineNumber));
508 	    break;
509 
510 	  case TK_EQUAL:
511 	    slcontext.addInst
512 		(new SimdBinaryOpInst <int, int, bool, EqualOp>
513 		 (node->lineNumber));
514 	    break;
515 
516 	  case TK_GREATER:
517 	    slcontext.addInst
518 		(new SimdBinaryOpInst <int, int, bool, GreaterOp>
519 		 (node->lineNumber));
520 	    break;
521 
522 	  case TK_GREATEREQUAL:
523 	    slcontext.addInst
524 		(new SimdBinaryOpInst <int, int, bool, GreaterEqualOp>
525 		 (node->lineNumber));
526 	    break;
527 
528 	  case TK_LEFTSHIFT:
529 	    slcontext.addInst
530 		(new SimdBinaryOpInst <int, int, int, LeftShiftOp>
531 		 (node->lineNumber));
532 	    break;
533 
534 	  case TK_LESS:
535 	    slcontext.addInst
536 		(new SimdBinaryOpInst <int, int, bool, LessOp>
537 		 (node->lineNumber));
538 	    break;
539 
540 	  case TK_LESSEQUAL:
541 	    slcontext.addInst
542 		(new SimdBinaryOpInst <int, int, bool, LessEqualOp>
543 		 (node->lineNumber));
544 	    break;
545 
546 	  case TK_MINUS:
547 	    slcontext.addInst
548 		(new SimdBinaryOpInst <int, int, int, BinaryMinusOp>
549 		 (node->lineNumber));
550 	    break;
551 
552 	  case TK_MOD:
553 	    slcontext.addInst
554 		(new SimdBinaryOpInst <int, int, int, ModOp>
555 		 (node->lineNumber));
556 	    break;
557 
558 	  case TK_NOTEQUAL:
559 	    slcontext.addInst
560 		(new SimdBinaryOpInst <int, int, bool, NotEqualOp>
561 		 (node->lineNumber));
562 	    break;
563 
564 	  case TK_PLUS:
565 	    slcontext.addInst
566 		(new SimdBinaryOpInst <int, int, int, PlusOp>
567 		 (node->lineNumber));
568 	    break;
569 
570 	  case TK_RIGHTSHIFT:
571 	    slcontext.addInst
572 		(new SimdBinaryOpInst <int, int, int, RightShiftOp>
573 		 (node->lineNumber));
574 	    break;
575 
576 	  case TK_TIMES:
577 	    slcontext.addInst
578 		(new SimdBinaryOpInst <int, int, int, TimesOp>
579 		 (node->lineNumber));
580 	    break;
581 
582 	  default:
583 
584 	    MESSAGE_LE (lcontext, ERR_OP_TYPE, node->lineNumber,
585 		"Invalid operand types "
586 		"for " << tokenAsString (binOp->op) << " operator "
587 		"(" << binOp->leftOperand->type->asString() << " " <<
588 		tokenAsString (binOp->op) << " " <<
589 		binOp->rightOperand->type->asString() << ").");
590 	}
591 
592 	return;
593     }
594 
595     if (node.cast<CallNode>())
596     {
597 	//
598 	// Push a placeholder for the return value for a call to
599 	// a function that returns an int.
600 	//
601 	slcontext.addInst (new SimdPushPlaceholderInst(alignedObjectSize(),
602 						       node->lineNumber));
603 	return;
604     }
605 }
606 
607 
608 
609 AddrPtr
newStaticVariable(Module * module) const610 SimdIntType::newStaticVariable (Module *module) const
611 {
612     return newStaticVariableGeneric(module, objectSize());
613 }
614 
615 void
newAutomaticVariable(StatementNodePtr node,LContext & lcontext) const616 SimdIntType::newAutomaticVariable (StatementNodePtr node,
617 				   LContext &lcontext) const
618 {
619     SimdLContext &slcontext = static_cast <SimdLContext &> (lcontext);
620     slcontext.addInst (new SimdPushPlaceholderInst
621 		       (objectSize(), node->lineNumber));
622 }
623 
624 
SimdUIntType()625 SimdUIntType::SimdUIntType (): UIntType ()
626 {
627     // empty
628 }
629 
630 
631 size_t
objectSize() const632 SimdUIntType::objectSize () const
633 {
634     return sizeof (unsigned int);
635 }
636 
637 
638 size_t
alignedObjectSize() const639 SimdUIntType::alignedObjectSize () const
640 {
641     return sizeof (unsigned int);
642 }
643 
644 
645 size_t
objectAlignment() const646 SimdUIntType::objectAlignment () const
647 {
648     return sizeof (unsigned int);
649 }
650 
651 
652 void
generateCastFrom(const ExprNodePtr & expr,LContext & lcontext) const653 SimdUIntType::generateCastFrom
654     (const ExprNodePtr &expr,
655      LContext &lcontext) const
656 {
657     SimdLContext &slcontext = static_cast <SimdLContext &> (lcontext);
658 
659     if (expr->type.cast<BoolType>())
660     {
661 	slcontext.addInst (new SimdUnaryOpInst <bool, unsigned, CopyOp>
662 			   (expr->lineNumber));
663 	return;
664     }
665 
666     if (expr->type.cast<IntType>())
667     {
668 	slcontext.addInst (new SimdUnaryOpInst <int, unsigned, CopyOp>
669 			   (expr->lineNumber));
670 	return;
671     }
672 
673     if (expr->type.cast<UIntType>())
674     {
675 	return;
676     }
677 
678     if (expr->type.cast<HalfType>())
679     {
680 	slcontext.addInst (new SimdUnaryOpInst <half, unsigned, CopyOp>
681 			   (expr->lineNumber));
682 	return;
683     }
684 
685     if (expr->type.cast<FloatType>())
686     {
687 	slcontext.addInst (new SimdUnaryOpInst <float, unsigned, CopyOp>
688 			   (expr->lineNumber));
689 	return;
690     }
691 
692     MESSAGE_LE (lcontext, ERR_TYPE, expr->lineNumber,
693 		"Cannot cast value of type " << expr->type->asString() <<
694 		" to type " << asString() << ".");
695 }
696 
697 
698 void
generateCode(const SyntaxNodePtr & node,LContext & lcontext) const699 SimdUIntType::generateCode
700     (const SyntaxNodePtr &node,
701      LContext &lcontext) const
702 {
703     SimdLContext &slcontext = static_cast <SimdLContext &> (lcontext);
704 
705     if (isAssignment (node))
706     {
707 	slcontext.addInst
708 	    (new SimdAssignInst (alignedObjectSize(), node->lineNumber));
709 	return;
710     }
711 
712     if (UnaryOpNodePtr unOp = node.cast<UnaryOpNode>())
713     {
714 	switch (unOp->op)
715 	{
716 	  case TK_BITNOT:
717 	    slcontext.addInst
718 		(new SimdUnaryOpInst <unsigned, unsigned, BitNotOp>
719 		 (node->lineNumber));
720 	    break;
721 
722 	  case TK_MINUS:
723 	    slcontext.addInst
724 		(new SimdUnaryOpInst <unsigned, int, UnaryMinusOp>
725 		 (node->lineNumber));
726 	    break;
727 
728 	  default:
729 
730 	    MESSAGE_LE (lcontext, ERR_OP_TYPE, node->lineNumber,
731 		"Cannot apply " << tokenAsString (unOp->op) << " "
732 		"operator to value of type " <<
733 		unOp->operand->type->asString() << ".");
734 	}
735 
736 	return;
737     }
738 
739     if (BinaryOpNodePtr binOp = node.cast<BinaryOpNode>())
740     {
741 	switch (binOp->op)
742 	{
743 	  case TK_BITAND:
744 	    slcontext.addInst
745 		(new SimdBinaryOpInst <unsigned, unsigned, unsigned, BitAndOp>
746 		 (node->lineNumber));
747 	    break;
748 
749 	  case TK_BITOR:
750 	    slcontext.addInst
751 		(new SimdBinaryOpInst <unsigned, unsigned, unsigned, BitOrOp>
752 		 (node->lineNumber));
753 	    break;
754 
755 	  case TK_BITXOR:
756 	    slcontext.addInst
757 		(new SimdBinaryOpInst <unsigned, unsigned, unsigned, BitXorOp>
758 		 (node->lineNumber));
759 	    break;
760 
761 	  case TK_DIV:
762 	    slcontext.addInst
763 		(new SimdBinaryOpInst <unsigned, unsigned, unsigned, IntDivOp>
764 		 (node->lineNumber));
765 	    break;
766 
767 	  case TK_EQUAL:
768 	    slcontext.addInst
769 		(new SimdBinaryOpInst <unsigned, unsigned, bool, EqualOp>
770 		 (node->lineNumber));
771 	    break;
772 
773 	  case TK_GREATER:
774 	    slcontext.addInst
775 		(new SimdBinaryOpInst <unsigned, unsigned, bool, GreaterOp>
776 		 (node->lineNumber));
777 	    break;
778 
779 	  case TK_GREATEREQUAL:
780 	    slcontext.addInst
781 		(new SimdBinaryOpInst <unsigned, unsigned, bool, GreaterEqualOp>
782 		 (node->lineNumber));
783 	    break;
784 
785 	  case TK_LEFTSHIFT:
786 	    slcontext.addInst
787 		(new SimdBinaryOpInst
788 			<unsigned, unsigned, unsigned, LeftShiftOp>
789 		 (node->lineNumber));
790 	    break;
791 
792 	  case TK_LESS:
793 	    slcontext.addInst
794 		(new SimdBinaryOpInst <unsigned, unsigned, bool, LessOp>
795 		 (node->lineNumber));
796 	    break;
797 
798 	  case TK_LESSEQUAL:
799 	    slcontext.addInst
800 		(new SimdBinaryOpInst <unsigned, unsigned, bool, LessEqualOp>
801 		 (node->lineNumber));
802 	    break;
803 
804 	  case TK_MINUS:
805 	    slcontext.addInst
806 		(new SimdBinaryOpInst
807 			<unsigned, unsigned, unsigned, BinaryMinusOp>
808 		 (node->lineNumber));
809 	    break;
810 
811 	  case TK_MOD:
812 	    slcontext.addInst
813 		(new SimdBinaryOpInst <unsigned, unsigned, unsigned, ModOp>
814 		 (node->lineNumber));
815 	    break;
816 
817 	  case TK_NOTEQUAL:
818 	    slcontext.addInst
819 		(new SimdBinaryOpInst <unsigned, unsigned, bool, NotEqualOp>
820 		 (node->lineNumber));
821 	    break;
822 
823 	  case TK_PLUS:
824 	    slcontext.addInst
825 		(new SimdBinaryOpInst <unsigned, unsigned, unsigned, PlusOp>
826 		 (node->lineNumber));
827 	    break;
828 
829 	  case TK_RIGHTSHIFT:
830 	    slcontext.addInst
831 		(new SimdBinaryOpInst
832 			<unsigned, unsigned, unsigned, RightShiftOp>
833 		 (node->lineNumber));
834 	    break;
835 
836 	  case TK_TIMES:
837 	    slcontext.addInst
838 		(new SimdBinaryOpInst <unsigned, unsigned, unsigned, TimesOp>
839 		 (node->lineNumber));
840 	    break;
841 
842 	  default:
843 
844 	    MESSAGE_LE (lcontext, ERR_OP_TYPE, node->lineNumber,
845 		"Invalid operand types "
846 		"for " << tokenAsString (binOp->op) << " operator "
847 		"(" << binOp->leftOperand->type->asString() << " " <<
848 		tokenAsString (binOp->op) << " " <<
849 		binOp->rightOperand->type->asString() << ").");
850 	}
851 
852 	return;
853     }
854 
855     if (node.cast<CallNode>())
856     {
857 	//
858 	// Push a placeholder for the return value for a call to
859 	// a function that returns an int.
860 	//
861 	slcontext.addInst
862 	    (new SimdPushPlaceholderInst (alignedObjectSize(),
863 					  node->lineNumber));
864 	return;
865     }
866 }
867 
868 
869 AddrPtr
newStaticVariable(Module * module) const870 SimdUIntType::newStaticVariable (Module *module) const
871 {
872     return newStaticVariableGeneric(module, objectSize());
873 }
874 
875 
876 void
newAutomaticVariable(StatementNodePtr node,LContext & lcontext) const877 SimdUIntType::newAutomaticVariable (StatementNodePtr node,
878 				   LContext &lcontext) const
879 {
880     SimdLContext &slcontext = static_cast <SimdLContext &> (lcontext);
881     slcontext.addInst (new SimdPushPlaceholderInst
882 		       (objectSize(), node->lineNumber));
883 }
884 
885 
SimdHalfType()886 SimdHalfType::SimdHalfType (): HalfType ()
887 {
888     // empty
889 }
890 
891 
892 size_t
objectSize() const893 SimdHalfType::objectSize () const
894 {
895     return sizeof (half);
896 }
897 
898 
899 size_t
alignedObjectSize() const900 SimdHalfType::alignedObjectSize () const
901 {
902     return sizeof (half);
903 }
904 
905 
906 size_t
objectAlignment() const907 SimdHalfType::objectAlignment () const
908 {
909     return sizeof (half);
910 }
911 
912 
913 void
generateCastFrom(const ExprNodePtr & expr,LContext & lcontext) const914 SimdHalfType::generateCastFrom
915     (const ExprNodePtr &expr,
916      LContext &lcontext) const
917 {
918     SimdLContext &slcontext = static_cast <SimdLContext &> (lcontext);
919 
920     if (expr->type.cast<BoolType>())
921     {
922 	slcontext.addInst (new SimdUnaryOpInst <bool, half, CopyOp>
923 			   (expr->lineNumber));
924 	return;
925     }
926 
927     if (expr->type.cast<IntType>())
928     {
929 	slcontext.addInst (new SimdUnaryOpInst <int, half, CopyOp>
930 			   (expr->lineNumber));
931 	return;
932     }
933 
934     if (expr->type.cast<UIntType>())
935     {
936 	slcontext.addInst (new SimdUnaryOpInst <unsigned, half, CopyOp>
937 			   (expr->lineNumber));
938 	return;
939     }
940 
941     if (expr->type.cast<HalfType>())
942     {
943 	return;
944     }
945 
946     if (expr->type.cast<FloatType>())
947     {
948 	slcontext.addInst (new SimdUnaryOpInst <float, half, CopyOp>
949 			   (expr->lineNumber));
950 	return;
951     }
952 
953     MESSAGE_LE (lcontext, ERR_TYPE, expr->lineNumber,
954 		"Cannot cast value of type " << expr->type->asString() <<
955 		" to type " << asString() << ".");
956 }
957 
958 
959 void
generateCode(const SyntaxNodePtr & node,LContext & lcontext) const960 SimdHalfType::generateCode
961     (const SyntaxNodePtr &node,
962      LContext &lcontext) const
963 {
964     SimdLContext &slcontext = static_cast <SimdLContext &> (lcontext);
965 
966     if (isAssignment (node))
967     {
968 	slcontext.addInst
969 	    (new SimdAssignInst (alignedObjectSize(), node->lineNumber));
970 	return;
971     }
972 
973     if (UnaryOpNodePtr unOp = node.cast<UnaryOpNode>())
974     {
975 	switch (unOp->op)
976 	{
977 	  case TK_MINUS:
978 	    slcontext.addInst
979 		(new SimdUnaryOpInst <half, half, UnaryMinusOp>
980 		 (node->lineNumber));
981 	    break;
982 
983 	  default:
984 
985 	    MESSAGE_LE (lcontext, ERR_OP_TYPE, node->lineNumber,
986 		"Cannot apply " << tokenAsString (unOp->op) << " "
987 		"operator to value of type " <<
988 		unOp->operand->type->asString() << ".");
989 	}
990 
991 	return;
992     }
993 
994     if (BinaryOpNodePtr binOp = node.cast<BinaryOpNode>())
995     {
996 	switch (binOp->op)
997 	{
998 	  case TK_DIV:
999 	    slcontext.addInst
1000 		(new SimdBinaryOpInst <half, half, half, DivOp>
1001 		 (node->lineNumber));
1002 	    break;
1003 
1004 	  case TK_EQUAL:
1005 	    slcontext.addInst
1006 		(new SimdBinaryOpInst <half, half, bool, EqualOp>
1007 		 (node->lineNumber));
1008 	    break;
1009 
1010 	  case TK_GREATER:
1011 	    slcontext.addInst
1012 		(new SimdBinaryOpInst <half, half, bool, GreaterOp>
1013 		 (node->lineNumber));
1014 	    break;
1015 
1016 	  case TK_GREATEREQUAL:
1017 	    slcontext.addInst
1018 		(new SimdBinaryOpInst <half, half, bool, GreaterEqualOp>
1019 		 (node->lineNumber));
1020 	    break;
1021 
1022 	  case TK_LESS:
1023 	    slcontext.addInst
1024 		(new SimdBinaryOpInst <half, half, bool, LessOp>
1025 		 (node->lineNumber));
1026 	    break;
1027 
1028 	  case TK_LESSEQUAL:
1029 	    slcontext.addInst
1030 		(new SimdBinaryOpInst <half, half, bool, LessEqualOp>
1031 		 (node->lineNumber));
1032 	    break;
1033 
1034 	  case TK_MINUS:
1035 	    slcontext.addInst
1036 		(new SimdBinaryOpInst <half, half, half, BinaryMinusOp>
1037 		 (node->lineNumber));
1038 	    break;
1039 
1040 	  case TK_NOTEQUAL:
1041 	    slcontext.addInst
1042 		(new SimdBinaryOpInst <half, half, bool, NotEqualOp>
1043 		 (node->lineNumber));
1044 	    break;
1045 
1046 	  case TK_PLUS:
1047 	    slcontext.addInst
1048 		(new SimdBinaryOpInst <half, half, half, PlusOp>
1049 		 (node->lineNumber));
1050 	    break;
1051 
1052 	  case TK_TIMES:
1053 	    slcontext.addInst
1054 		(new SimdBinaryOpInst <half, half, half, TimesOp>
1055 		 (node->lineNumber));
1056 	    break;
1057 
1058 	  default:
1059 
1060 	    MESSAGE_LE (lcontext, ERR_OP_TYPE, node->lineNumber,
1061 		"Invalid operand types "
1062 		"for " << tokenAsString (binOp->op) << " operator "
1063 		"(" << binOp->leftOperand->type->asString() << " " <<
1064 		tokenAsString (binOp->op) << " " <<
1065 		binOp->rightOperand->type->asString() << ").");
1066 	}
1067 
1068 	return;
1069     }
1070 
1071     if (node.cast<CallNode>())
1072     {
1073 	//
1074 	// Push a placeholder for the return value for a call to
1075 	// a function that returns an int.
1076 	//
1077 
1078 	slcontext.addInst
1079 	    (new SimdPushPlaceholderInst (alignedObjectSize(),
1080 					  node->lineNumber));
1081 	return;
1082     }
1083 }
1084 
1085 
1086 AddrPtr
newStaticVariable(Module * module) const1087 SimdHalfType::newStaticVariable (Module *module) const
1088 {
1089     return newStaticVariableGeneric(module, objectSize());
1090 }
1091 
1092 
1093 void
newAutomaticVariable(StatementNodePtr node,LContext & lcontext) const1094 SimdHalfType::newAutomaticVariable (StatementNodePtr node,
1095 				    LContext &lcontext) const
1096 {
1097     SimdLContext &slcontext = static_cast <SimdLContext &> (lcontext);
1098     slcontext.addInst (new SimdPushPlaceholderInst
1099 		       (objectSize(), node->lineNumber));
1100 }
1101 
1102 
SimdFloatType()1103 SimdFloatType::SimdFloatType (): FloatType ()
1104 {
1105     // empty
1106 }
1107 
1108 
1109 size_t
objectSize() const1110 SimdFloatType::objectSize () const
1111 {
1112     return sizeof (float);
1113 }
1114 
1115 
1116 size_t
alignedObjectSize() const1117 SimdFloatType::alignedObjectSize () const
1118 {
1119     return sizeof (float);
1120 }
1121 
1122 
1123 size_t
objectAlignment() const1124 SimdFloatType::objectAlignment () const
1125 {
1126     return sizeof (float);
1127 }
1128 
1129 
1130 void
generateCastFrom(const ExprNodePtr & expr,LContext & lcontext) const1131 SimdFloatType::generateCastFrom
1132     (const ExprNodePtr &expr,
1133      LContext &lcontext) const
1134 {
1135     SimdLContext &slcontext = static_cast <SimdLContext &> (lcontext);
1136 
1137     if (expr->type.cast<BoolType>())
1138     {
1139 	slcontext.addInst (new SimdUnaryOpInst <bool, float, CopyOp>
1140 			   (expr->lineNumber));
1141 	return;
1142     }
1143 
1144     if (expr->type.cast<IntType>())
1145     {
1146 	slcontext.addInst (new SimdUnaryOpInst <int, float, CopyOp>
1147 			   (expr->lineNumber));
1148 	return;
1149     }
1150 
1151     if (expr->type.cast<UIntType>())
1152     {
1153 	slcontext.addInst (new SimdUnaryOpInst <unsigned, float, CopyOp>
1154 			   (expr->lineNumber));
1155 	return;
1156     }
1157 
1158     if (expr->type.cast<HalfType>())
1159     {
1160 	slcontext.addInst (new SimdUnaryOpInst <half, float, CopyOp>
1161 			   (expr->lineNumber));
1162 	return;
1163     }
1164 
1165     if (expr->type.cast<FloatType>())
1166     {
1167 	return;
1168     }
1169 
1170     MESSAGE_LE (lcontext, ERR_TYPE, expr->lineNumber,
1171 		"Cannot cast value of type " << expr->type->asString() <<
1172 		" to type " << asString() << ".");
1173 }
1174 
1175 
1176 void
generateCode(const SyntaxNodePtr & node,LContext & lcontext) const1177 SimdFloatType::generateCode
1178     (const SyntaxNodePtr &node,
1179      LContext &lcontext) const
1180 {
1181     SimdLContext &slcontext = static_cast <SimdLContext &> (lcontext);
1182 
1183     if (isAssignment (node))
1184     {
1185 	slcontext.addInst
1186 	    (new SimdAssignInst(alignedObjectSize(), node->lineNumber));
1187 	return;
1188     }
1189 
1190     if (UnaryOpNodePtr unOp = node.cast<UnaryOpNode>())
1191     {
1192 	switch (unOp->op)
1193 	{
1194 	  case TK_MINUS:
1195 	    slcontext.addInst
1196 		(new SimdUnaryOpInst <float, float, UnaryMinusOp>
1197 		 (node->lineNumber));
1198 	    break;
1199 
1200 	  default:
1201 
1202 	    MESSAGE_LE (lcontext, ERR_OP_TYPE, node->lineNumber,
1203 		"Cannot apply " << tokenAsString (unOp->op) << " "
1204 		"operator to value of type " <<
1205 		unOp->operand->type->asString() << ".");
1206 	}
1207 
1208 	return;
1209     }
1210 
1211     if (BinaryOpNodePtr binOp = node.cast<BinaryOpNode>())
1212     {
1213 	switch (binOp->op)
1214 	{
1215 	  case TK_DIV:
1216 	    slcontext.addInst
1217 		(new SimdBinaryOpInst <float, float, float, DivOp>
1218 		 (node->lineNumber));
1219 	    break;
1220 
1221 	  case TK_EQUAL:
1222 	    slcontext.addInst
1223 		(new SimdBinaryOpInst <float, float, bool, EqualOp>
1224 		 (node->lineNumber));
1225 	    break;
1226 
1227 	  case TK_GREATER:
1228 	    slcontext.addInst
1229 		(new SimdBinaryOpInst <float, float, bool, GreaterOp>
1230 		 (node->lineNumber));
1231 	    break;
1232 
1233 	  case TK_GREATEREQUAL:
1234 	    slcontext.addInst
1235 		(new SimdBinaryOpInst <float, float, bool, GreaterEqualOp>
1236 		 (node->lineNumber));
1237 	    break;
1238 
1239 	  case TK_LESS:
1240 	    slcontext.addInst
1241 		(new SimdBinaryOpInst <float, float, bool, LessOp>
1242 		 (node->lineNumber));
1243 	    break;
1244 
1245 	  case TK_LESSEQUAL:
1246 	    slcontext.addInst
1247 		(new SimdBinaryOpInst <float, float, bool, LessEqualOp>
1248 		 (node->lineNumber));
1249 	    break;
1250 
1251 	  case TK_MINUS:
1252 	    slcontext.addInst
1253 		(new SimdBinaryOpInst <float, float, float, BinaryMinusOp>
1254 		 (node->lineNumber));
1255 	    break;
1256 
1257 	  case TK_NOTEQUAL:
1258 	    slcontext.addInst
1259 		(new SimdBinaryOpInst <float, float, bool, NotEqualOp>
1260 		 (node->lineNumber));
1261 	    break;
1262 
1263 	  case TK_PLUS:
1264 	    slcontext.addInst
1265 		(new SimdBinaryOpInst <float, float, float, PlusOp>
1266 		 (node->lineNumber));
1267 	    break;
1268 
1269 	  case TK_TIMES:
1270 	    slcontext.addInst
1271 		(new SimdBinaryOpInst <float, float, float, TimesOp>
1272 		 (node->lineNumber));
1273 	    break;
1274 
1275 	  default:
1276 
1277 	    MESSAGE_LE (lcontext, ERR_OP_TYPE, node->lineNumber,
1278 		"Invalid operand types "
1279 		"for " << tokenAsString (binOp->op) << " operator "
1280 		"(" << binOp->leftOperand->type->asString() << " " <<
1281 		tokenAsString (binOp->op) << " " <<
1282 		binOp->rightOperand->type->asString() << ").");
1283 	}
1284 
1285 	return;
1286     }
1287 
1288     if (node.cast<CallNode>())
1289     {
1290 	//
1291 	// Push a placeholder for the return value for a call to
1292 	// a function that returns an int.
1293 	//
1294 
1295 	slcontext.addInst (new SimdPushPlaceholderInst (alignedObjectSize(),
1296 						        node->lineNumber));
1297 	return;
1298     }
1299 }
1300 
1301 
1302 AddrPtr
newStaticVariable(Module * module) const1303 SimdFloatType::newStaticVariable (Module *module) const
1304 {
1305     return newStaticVariableGeneric(module, objectSize());
1306 }
1307 
1308 
1309 void
newAutomaticVariable(StatementNodePtr node,LContext & lcontext) const1310 SimdFloatType::newAutomaticVariable (StatementNodePtr node,
1311 				     LContext &lcontext) const
1312 {
1313     SimdLContext &slcontext = static_cast <SimdLContext &> (lcontext);
1314     slcontext.addInst (new SimdPushPlaceholderInst
1315 		       (objectSize(), node->lineNumber));
1316 }
1317 
1318 
SimdStringType()1319 SimdStringType::SimdStringType (): StringType ()
1320 {
1321     // empty
1322 }
1323 
1324 
1325 size_t
objectSize() const1326 SimdStringType::objectSize () const
1327 {
1328     return sizeof (string *);
1329 }
1330 
1331 
1332 size_t
alignedObjectSize() const1333 SimdStringType::alignedObjectSize () const
1334 {
1335     return sizeof (string *);
1336 }
1337 
1338 
1339 size_t
objectAlignment() const1340 SimdStringType::objectAlignment () const
1341 {
1342     return sizeof (string *);
1343 }
1344 
1345 
1346 void
generateCastFrom(const ExprNodePtr & expr,LContext & lcontext) const1347 SimdStringType::generateCastFrom
1348     (const ExprNodePtr &expr,
1349      LContext &lcontext) const
1350 {
1351     if (expr->type.cast<StringType>())
1352     {
1353 	return;
1354     }
1355 
1356     MESSAGE_LE (lcontext, ERR_TYPE, expr->lineNumber,
1357 		"Cannot cast value of type " << expr->type->asString() <<
1358 		" to type " << asString() << ".");
1359 }
1360 
1361 
1362 void
generateCode(const SyntaxNodePtr & node,LContext & lcontext) const1363 SimdStringType::generateCode
1364     (const SyntaxNodePtr &node,
1365      LContext &lcontext) const
1366 {
1367     SimdLContext &slcontext = static_cast <SimdLContext &> (lcontext);
1368 
1369     if (isAssignment (node))
1370     {
1371 	slcontext.addInst
1372 	    (new SimdAssignInst (alignedObjectSize(), node->lineNumber));
1373 	return;
1374     }
1375 
1376     if (UnaryOpNodePtr unOp = node.cast<UnaryOpNode>())
1377     {
1378 	switch (unOp->op)
1379 	{
1380 	  default:
1381 
1382 	    MESSAGE_LE (lcontext, ERR_OP_TYPE, node->lineNumber,
1383 		"Cannot apply " << tokenAsString (unOp->op) << " "
1384 		"operator to value of type " <<
1385 		unOp->operand->type->asString() << ".");
1386 	}
1387 
1388 	return;
1389     }
1390 
1391     if (BinaryOpNodePtr binOp = node.cast<BinaryOpNode>())
1392     {
1393 	switch (binOp->op)
1394 	{
1395 	  default:
1396 
1397 	    MESSAGE_LE (lcontext, ERR_OP_TYPE, node->lineNumber,
1398 		"Invalid operand types "
1399 		"for " << tokenAsString (binOp->op) << " operator "
1400 		"(" << binOp->leftOperand->type->asString() << " " <<
1401 		tokenAsString (binOp->op) << " " <<
1402 		binOp->rightOperand->type->asString() << ").");
1403 	}
1404 
1405 	return;
1406     }
1407 
1408     if (node.cast<CallNode>())
1409     {
1410 	//
1411 	// Push a placeholder for the return value for a call to
1412 	// a function that returns an int.
1413 	//
1414 
1415 	slcontext.addInst (new SimdPushPlaceholderInst (alignedObjectSize(),
1416 	                                                node->lineNumber));
1417 	return;
1418     }
1419 }
1420 
1421 
1422 AddrPtr
newStaticVariable(Module * module) const1423 SimdStringType::newStaticVariable (Module *module) const
1424 {
1425     return newStaticVariableGeneric (module, alignedObjectSize());
1426 }
1427 
1428 
1429 void
newAutomaticVariable(StatementNodePtr node,LContext & lcontext) const1430 SimdStringType::newAutomaticVariable (StatementNodePtr node,
1431 				     LContext &lcontext) const
1432 {
1433     SimdLContext &slcontext = static_cast <SimdLContext &> (lcontext);
1434 
1435     slcontext.addInst (new SimdPushPlaceholderInst
1436 			       (alignedObjectSize(), node->lineNumber));
1437 }
1438 
1439 
SimdArrayType(const DataTypePtr & elementType,int size,SimdLContext * lcontext)1440 SimdArrayType::SimdArrayType (const DataTypePtr &elementType, int size,
1441 			      SimdLContext *lcontext /* = 0 */):
1442     ArrayType (elementType, size),
1443     _unknownSize(0),
1444     _unknownESize(0)
1445 {
1446     if( lcontext)
1447     {
1448 	// If size is not specified, this is a function parameter
1449 	// size will be stored as a parameter
1450 	if( size == 0 )
1451 	{
1452 	    IntTypePtr intType = lcontext->newIntType ();
1453 	    _unknownSize = lcontext->parameterAddr (intType);
1454 	}
1455 
1456 	// if the element size is not known, create a local variable
1457 	// to store the element size computed later
1458 	SimdArrayTypePtr at = elementType.cast<SimdArrayType>();
1459 	if( at && (at->unknownElementSize() || at->unknownSize() ))
1460 	{
1461 	    IntTypePtr intType = lcontext->newIntType ();
1462 	    _unknownESize = lcontext->autoVariableAddr (intType);
1463 	}
1464     }
1465 }
1466 
1467 
1468 size_t
objectSize() const1469 SimdArrayType::objectSize () const
1470 {
1471     return elementSize() * size();
1472 }
1473 
1474 
1475 size_t
alignedObjectSize() const1476 SimdArrayType::alignedObjectSize () const
1477 {
1478     return elementSize() * size();
1479 }
1480 
1481 
1482 size_t
objectAlignment() const1483 SimdArrayType::objectAlignment () const
1484 {
1485     return elementType()->objectAlignment();
1486 }
1487 
1488 SimdDataAddrPtr
unknownElementSize() const1489 SimdArrayType::unknownElementSize () const
1490 {
1491     return _unknownESize;
1492 }
1493 
1494 SimdDataAddrPtr
unknownSize() const1495 SimdArrayType::unknownSize () const
1496 {
1497     return _unknownSize;
1498 }
1499 
1500 void
generateCastFrom(const ExprNodePtr & expr,LContext & lcontext) const1501 SimdArrayType::generateCastFrom
1502     (const ExprNodePtr &expr,
1503      LContext &lcontext) const
1504 {
1505     assert(isSameTypeAs(expr->type));
1506     return;
1507 }
1508 
1509 
1510 void
generateCode(const SyntaxNodePtr & node,LContext & lcontext) const1511 SimdArrayType::generateCode
1512     (const SyntaxNodePtr &node,
1513      LContext &lcontext) const
1514 {
1515     SimdLContext &slcontext = static_cast <SimdLContext &> (lcontext);
1516 
1517     VariableNodePtr var = node.cast<VariableNode>();
1518     if( var && var->initialValue.cast<ValueNode>())
1519     {
1520 	SizeVector sizes;
1521 	SizeVector offsets;
1522 	coreSizes(0, sizes, offsets);
1523  	slcontext.addInst (new SimdInitializeInst(sizes,
1524 						  offsets,
1525 						  node->lineNumber));
1526 	return;
1527     }
1528     else if (isAssignment(node))  // return or assignment
1529     {
1530 	slcontext.addInst (new SimdAssignArrayInst
1531 			     (size(), elementSize(), node->lineNumber));
1532 	return;
1533     }
1534     else if ( node.cast<ArrayIndexNode>() )
1535     {
1536 	if(unknownSize() || unknownElementSize())
1537 	{
1538 
1539 	    slcontext.addInst (new SimdIndexVSArrayInst(elementSize(),
1540 							unknownElementSize(),
1541 							size(),
1542 							unknownSize(),
1543 							node->lineNumber));
1544 	}
1545 	else
1546 	{
1547 	    slcontext.addInst (new SimdIndexArrayInst(elementSize(),
1548 						      node->lineNumber,
1549 						      size()));
1550 	}
1551 	return;
1552     }
1553     else if (node.cast<SizeNode>())
1554     {
1555 	assert(size() == 0);
1556 	slcontext.addInst (new SimdPushRefInst (unknownSize(),
1557 						node->lineNumber));
1558     }
1559     else if (node.cast<CallNode>())
1560     {
1561 	slcontext.addInst (new SimdPushPlaceholderInst(objectSize(),
1562 						       node->lineNumber));
1563 	return;
1564     }
1565 }
1566 
1567 
1568 AddrPtr
newStaticVariable(Module * module) const1569 SimdArrayType::newStaticVariable (Module *module) const
1570 {
1571     return newStaticVariableGeneric(module, objectSize());
1572 }
1573 
1574 
1575 void
newAutomaticVariable(StatementNodePtr node,LContext & lcontext) const1576 SimdArrayType::newAutomaticVariable (StatementNodePtr node,
1577 				      LContext &lcontext ) const
1578 {
1579     SimdLContext &slcontext = static_cast <SimdLContext &> (lcontext);
1580     slcontext.addInst (new SimdPushPlaceholderInst
1581 		       (objectSize(), node->lineNumber));
1582 }
1583 
1584 
1585 
SimdStructType(const string & name,const MemberVector & members)1586 SimdStructType::SimdStructType
1587     (const string &name,
1588      const MemberVector &members)
1589 :
1590     StructType (name, members),
1591     _objectSize (0),
1592     _alignedObjectSize (0),
1593     _objectAlignment (1)
1594 {
1595     for (size_t i = 0; i < this->members().size(); ++i)
1596     {
1597 	Member &m = member (i);
1598 
1599 	m.offset = align (_objectSize, m.type->objectAlignment());
1600 	_objectSize = m.offset + m.type->objectSize();
1601 
1602 	_objectAlignment =
1603 	    leastCommonMultiple (_objectAlignment, m.type->objectAlignment());
1604     }
1605 
1606     _alignedObjectSize = align (_objectSize, _objectAlignment);
1607 }
1608 
1609 
1610 size_t
objectSize() const1611 SimdStructType::objectSize () const
1612 {
1613     return _objectSize;
1614 }
1615 
1616 
1617 size_t
alignedObjectSize() const1618 SimdStructType::alignedObjectSize () const
1619 {
1620     return _alignedObjectSize;
1621 }
1622 
1623 
1624 size_t
objectAlignment() const1625 SimdStructType::objectAlignment () const
1626 {
1627     return _objectAlignment;
1628 }
1629 
1630 
1631 void
generateCastFrom(const ExprNodePtr & expr,LContext & lcontext) const1632 SimdStructType::generateCastFrom
1633     (const ExprNodePtr &expr,
1634      LContext &lcontext) const
1635 {
1636     return;
1637 }
1638 
1639 
1640 void
generateCode(const SyntaxNodePtr & node,LContext & lcontext) const1641 SimdStructType::generateCode
1642     (const SyntaxNodePtr &node,
1643      LContext &lcontext) const
1644 {
1645     SimdLContext &slcontext = static_cast <SimdLContext &> (lcontext);
1646 
1647     VariableNodePtr var = node.cast<VariableNode>();
1648     if( var && var->initialValue.cast<ValueNode>())
1649     {
1650 	SizeVector sizes;
1651 	SizeVector offsets;
1652 	coreSizes(0, sizes, offsets);
1653  	slcontext.addInst (new SimdInitializeInst(sizes,
1654 						  offsets,
1655 						  node->lineNumber));
1656 	return;
1657     }
1658 
1659     if( MemberNodePtr mem = node.cast<MemberNode>() )
1660     {
1661  	slcontext.addInst (new SimdAccessMemberInst(mem->offset,
1662  						       (node->lineNumber)));
1663 	return;
1664     }
1665 
1666     if (isAssignment (node))
1667     {
1668 	slcontext.addInst (new SimdAssignInst
1669 			     (alignedObjectSize(), node->lineNumber));
1670 	return;
1671     }
1672 
1673     if (node.cast<CallNode>())
1674     {
1675 	// Push a placeholder for the return value for a call to
1676 	// a function that returns a struct
1677 	slcontext.addInst (new SimdPushPlaceholderInst (alignedObjectSize(),
1678 						        node->lineNumber));
1679 	return;
1680     }
1681 }
1682 
1683 
1684 AddrPtr
newStaticVariable(Module * module) const1685 SimdStructType::newStaticVariable (Module *module) const
1686 {
1687     return newStaticVariableGeneric(module, alignedObjectSize());
1688 }
1689 
1690 
1691 void
newAutomaticVariable(StatementNodePtr node,LContext & lcontext) const1692 SimdStructType::newAutomaticVariable (StatementNodePtr node,
1693 				      LContext &lcontext ) const
1694 {
1695     SimdLContext &slcontext = static_cast <SimdLContext &> (lcontext);
1696     slcontext.addInst (new SimdPushPlaceholderInst
1697 		       (alignedObjectSize(), node->lineNumber));
1698 }
1699 
1700 
SimdFunctionType(const DataTypePtr & returnType,bool returnVarying,const ParamVector & parameters)1701 SimdFunctionType::SimdFunctionType
1702     (const DataTypePtr &returnType,
1703      bool returnVarying,
1704      const ParamVector &parameters)
1705 :
1706     FunctionType (returnType, returnVarying, parameters)
1707 {
1708     // empty
1709 }
1710 
1711 
1712 void
generateCastFrom(const ExprNodePtr & expr,LContext & lcontext) const1713 SimdFunctionType::generateCastFrom
1714     (const ExprNodePtr &expr,
1715      LContext &lcontext) const
1716 {
1717     // empty
1718 }
1719 
1720 
1721 void
generateCode(const SyntaxNodePtr & node,LContext & lcontext) const1722 SimdFunctionType::generateCode
1723     (const SyntaxNodePtr &node,
1724      LContext &lcontext) const
1725 {
1726     // empty
1727 }
1728 
1729 
1730 } // namespace Ctl
1731 
1732