blob: d7697f24f7afd7bb95b0b6c2ee595b78406413bf [file] [log] [blame]
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001//
Nicolas Capens6ed8d8a2014-06-11 11:25:20 -04002// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00003// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7//
8// Build the intermediate representation.
9//
10
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000011#include <float.h>
alokp@chromium.org1bcc3fd2010-05-19 17:08:44 +000012#include <limits.h>
alokp@chromium.org32cfaf42010-08-23 21:01:13 +000013#include <algorithm>
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000014
Jamie Madillb1a85f42014-08-19 15:23:24 -040015#include "compiler/translator/Intermediate.h"
Geoff Lang17732822013-08-29 13:46:49 -040016#include "compiler/translator/SymbolTable.h"
daniel@transgaming.combbf56f72010-04-20 18:52:13 +000017
Jamie Madill45bcc782016-11-07 13:58:48 -050018namespace sh
19{
20
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000021////////////////////////////////////////////////////////////////////////////
22//
23// First set of functions are to help build the intermediate representation.
24// These functions are not member functions of the nodes.
25// They are called from parser productions.
26//
27/////////////////////////////////////////////////////////////////////////////
28
29//
30// Add a terminal node for an identifier in an expression.
31//
32// Returns the added node.
33//
Jamie Madilld7b1ab52016-12-12 14:42:19 -050034TIntermSymbol *TIntermediate::addSymbol(int id,
35 const TString &name,
36 const TType &type,
37 const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000038{
Zhenyao Moe40d1e92014-07-16 17:40:36 -070039 TIntermSymbol *node = new TIntermSymbol(id, name, type);
alokp@chromium.org2cf17712010-03-30 20:33:18 +000040 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000041
alokp@chromium.org2cf17712010-03-30 20:33:18 +000042 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000043}
44
45//
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000046// Connect two nodes through an index operator, where the left node is the base
47// of an array or struct, and the right node is a direct or indirect offset.
48//
49// Returns the added node.
50// The caller should set the type of the returned node.
51//
Olli Etuaho3272a6d2016-08-29 17:54:50 +030052TIntermTyped *TIntermediate::addIndex(TOperator op,
53 TIntermTyped *base,
54 TIntermTyped *index,
55 const TSourceLoc &line,
56 TDiagnostics *diagnostics)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000057{
Olli Etuaho3272a6d2016-08-29 17:54:50 +030058 TIntermBinary *node = new TIntermBinary(op, base, index);
alokp@chromium.org2cf17712010-03-30 20:33:18 +000059 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000060
Olli Etuaho3272a6d2016-08-29 17:54:50 +030061 TIntermTyped *folded = node->fold(diagnostics);
62 if (folded)
63 {
64 return folded;
65 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000066
alokp@chromium.org2cf17712010-03-30 20:33:18 +000067 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000068}
69
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000070// This is the safe way to change the operator on an aggregate, as it
71// does lots of error checking and fixing. Especially for establishing
Olli Etuaho6d40bbd2016-09-30 13:49:38 +010072// a function call's operation on it's set of parameters.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000073//
74// Returns an aggregate node, which could be the one passed in if
daniel@transgaming.com978702d2012-04-04 15:05:58 +000075// it was already an aggregate but no operator was set.
Jamie Madilld7b1ab52016-12-12 14:42:19 -050076TIntermAggregate *TIntermediate::setAggregateOperator(TIntermNode *node,
77 TOperator op,
78 const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000079{
Zhenyao Moe40d1e92014-07-16 17:40:36 -070080 TIntermAggregate *aggNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000081
alokp@chromium.org2cf17712010-03-30 20:33:18 +000082 //
83 // Make sure we have an aggregate. If not turn it into one.
84 //
Zhenyao Moe40d1e92014-07-16 17:40:36 -070085 if (node)
86 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +000087 aggNode = node->getAsAggregate();
Zhenyao Moe40d1e92014-07-16 17:40:36 -070088 if (aggNode == NULL || aggNode->getOp() != EOpNull)
89 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +000090 //
91 // Make an aggregate containing this node.
92 //
93 aggNode = new TIntermAggregate();
Zhenyao Moe40d1e92014-07-16 17:40:36 -070094 aggNode->getSequence()->push_back(node);
alokp@chromium.org2cf17712010-03-30 20:33:18 +000095 }
Zhenyao Moe40d1e92014-07-16 17:40:36 -070096 }
97 else
98 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +000099 aggNode = new TIntermAggregate();
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700100 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000101
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000102 //
103 // Set the operator.
104 //
alokp@chromium.org58e54292010-08-24 21:40:03 +0000105 aggNode->setOp(op);
Jamie Madill075edd82013-07-08 13:30:19 -0400106 aggNode->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000107
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000108 return aggNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000109}
110
111//
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000112// Safe way to combine two nodes into an aggregate. Works with null pointers,
113// a node that's not a aggregate yet, etc.
114//
115// Returns the resulting aggregate, unless 0 was passed in for
116// both existing nodes.
117//
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500118TIntermAggregate *TIntermediate::growAggregate(TIntermNode *left,
119 TIntermNode *right,
120 const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000121{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700122 if (left == NULL && right == NULL)
123 return NULL;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000124
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700125 TIntermAggregate *aggNode = NULL;
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000126 if (left)
127 aggNode = left->getAsAggregate();
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700128 if (!aggNode || aggNode->getOp() != EOpNull)
129 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000130 aggNode = new TIntermAggregate;
131 if (left)
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700132 aggNode->getSequence()->push_back(left);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000133 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000134
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000135 if (right)
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700136 aggNode->getSequence()->push_back(right);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000137
Jamie Madill075edd82013-07-08 13:30:19 -0400138 aggNode->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000139
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000140 return aggNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000141}
142
143//
144// Turn an existing node into an aggregate.
145//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700146// Returns an aggregate, unless NULL was passed in for the existing node.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000147//
Olli Etuaho32db19b2016-10-04 14:43:16 +0100148TIntermAggregate *TIntermediate::MakeAggregate(TIntermNode *node, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000149{
Olli Etuaho32db19b2016-10-04 14:43:16 +0100150 if (node == nullptr)
151 return nullptr;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000152
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700153 TIntermAggregate *aggNode = new TIntermAggregate;
154 aggNode->getSequence()->push_back(node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000155
Jamie Madill075edd82013-07-08 13:30:19 -0400156 aggNode->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000157
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000158 return aggNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000159}
160
Olli Etuaho7d7f8c42015-05-19 18:38:49 +0300161// If the input node is nullptr, return nullptr.
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100162// If the input node is a block node, return it.
163// If the input node is not a block node, put it inside a block node and return that.
164TIntermBlock *TIntermediate::EnsureBlock(TIntermNode *node)
Olli Etuaho7d7f8c42015-05-19 18:38:49 +0300165{
166 if (node == nullptr)
167 return nullptr;
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100168 TIntermBlock *blockNode = node->getAsBlock();
169 if (blockNode != nullptr)
170 return blockNode;
Olli Etuaho7d7f8c42015-05-19 18:38:49 +0300171
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100172 blockNode = new TIntermBlock();
173 blockNode->setLine(node->getLine());
174 blockNode->getSequence()->push_back(node);
175 return blockNode;
Olli Etuaho7d7f8c42015-05-19 18:38:49 +0300176}
177
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000178// For "if" test nodes. There are three children; a condition,
179// a true path, and a false path. The two paths are in the
180// nodePair.
181//
Olli Etuaho57961272016-09-14 13:57:46 +0300182// Returns the node created.
183TIntermNode *TIntermediate::addIfElse(TIntermTyped *cond,
184 TIntermNodePair nodePair,
185 const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000186{
Olli Etuaho57961272016-09-14 13:57:46 +0300187 // For compile time constant conditions, prune the code now.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000188
Olli Etuaho7c3848e2015-11-04 13:19:17 +0200189 if (cond->getAsConstantUnion())
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700190 {
shannon.woods%transgaming.com@gtempaccount.comc0d0c222013-04-13 03:29:36 +0000191 if (cond->getAsConstantUnion()->getBConst(0) == true)
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700192 {
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100193 return EnsureBlock(nodePair.node1);
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700194 }
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000195 else
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700196 {
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100197 return EnsureBlock(nodePair.node2);
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700198 }
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000199 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000200
Olli Etuaho57961272016-09-14 13:57:46 +0300201 TIntermIfElse *node =
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100202 new TIntermIfElse(cond, EnsureBlock(nodePair.node1), EnsureBlock(nodePair.node2));
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000203 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000204
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000205 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000206}
207
Olli Etuaho4db7ded2016-10-13 12:23:11 +0100208TIntermTyped *TIntermediate::AddComma(TIntermTyped *left,
Olli Etuaho15200042015-11-04 16:56:31 +0200209 TIntermTyped *right,
210 const TSourceLoc &line,
211 int shaderVersion)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000212{
Olli Etuaho15200042015-11-04 16:56:31 +0200213 TIntermTyped *commaNode = nullptr;
214 if (!left->hasSideEffects())
215 {
216 commaNode = right;
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700217 }
218 else
219 {
Olli Etuaho4db7ded2016-10-13 12:23:11 +0100220 commaNode = new TIntermBinary(EOpComma, left, right);
221 commaNode->setLine(line);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000222 }
Olli Etuaho4db7ded2016-10-13 12:23:11 +0100223 TQualifier resultQualifier = TIntermBinary::GetCommaQualifier(shaderVersion, left, right);
Olli Etuaho15200042015-11-04 16:56:31 +0200224 commaNode->getTypePointer()->setQualifier(resultQualifier);
225 return commaNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000226}
227
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000228// For "?:" test nodes. There are three children; a condition,
229// a true path, and a false path. The two paths are specified
230// as separate parameters.
231//
Olli Etuahod0bad2c2016-09-09 18:01:16 +0300232// Returns the ternary node created, or one of trueExpression and falseExpression if the expression
233// could be folded.
234TIntermTyped *TIntermediate::AddTernarySelection(TIntermTyped *cond,
235 TIntermTyped *trueExpression,
236 TIntermTyped *falseExpression,
237 const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000238{
Olli Etuaho7c3848e2015-11-04 13:19:17 +0200239 // Note that the node resulting from here can be a constant union without being qualified as
240 // constant.
241 if (cond->getAsConstantUnion())
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700242 {
Olli Etuahod0bad2c2016-09-09 18:01:16 +0300243 TQualifier resultQualifier =
244 TIntermTernary::DetermineQualifier(cond, trueExpression, falseExpression);
shannon.woods%transgaming.com@gtempaccount.comc0d0c222013-04-13 03:29:36 +0000245 if (cond->getAsConstantUnion()->getBConst(0))
Olli Etuaho7c3848e2015-11-04 13:19:17 +0200246 {
Olli Etuahod0bad2c2016-09-09 18:01:16 +0300247 trueExpression->getTypePointer()->setQualifier(resultQualifier);
248 return trueExpression;
Olli Etuaho7c3848e2015-11-04 13:19:17 +0200249 }
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000250 else
Olli Etuaho7c3848e2015-11-04 13:19:17 +0200251 {
Olli Etuahod0bad2c2016-09-09 18:01:16 +0300252 falseExpression->getTypePointer()->setQualifier(resultQualifier);
253 return falseExpression;
Olli Etuaho7c3848e2015-11-04 13:19:17 +0200254 }
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000255 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000256
Olli Etuahod0bad2c2016-09-09 18:01:16 +0300257 // Make a ternary node.
258 TIntermTernary *node = new TIntermTernary(cond, trueExpression, falseExpression);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000259 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000260
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000261 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000262}
263
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100264TIntermSwitch *TIntermediate::addSwitch(TIntermTyped *init,
265 TIntermBlock *statementList,
266 const TSourceLoc &line)
Olli Etuahoa3a36662015-02-17 13:46:51 +0200267{
Olli Etuaho3c1dfb52015-02-20 11:34:03 +0200268 TIntermSwitch *node = new TIntermSwitch(init, statementList);
269 node->setLine(line);
270
271 return node;
Olli Etuahoa3a36662015-02-17 13:46:51 +0200272}
273
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500274TIntermCase *TIntermediate::addCase(TIntermTyped *condition, const TSourceLoc &line)
Olli Etuahoa3a36662015-02-17 13:46:51 +0200275{
Olli Etuaho3c1dfb52015-02-20 11:34:03 +0200276 TIntermCase *node = new TIntermCase(condition);
277 node->setLine(line);
278
279 return node;
Olli Etuahoa3a36662015-02-17 13:46:51 +0200280}
281
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000282//
283// Constant terminal nodes. Has a union that contains bool, float or int constants
284//
285// Returns the constant union node created.
286//
287
Olli Etuaho5c0e0232015-11-11 15:55:59 +0200288TIntermConstantUnion *TIntermediate::addConstantUnion(const TConstantUnion *constantUnion,
289 const TType &type,
290 const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000291{
Jamie Madillb11e2482015-05-04 14:21:22 -0400292 TIntermConstantUnion *node = new TIntermConstantUnion(constantUnion, type);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000293 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000294
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000295 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000296}
297
Olli Etuahob6fa0432016-09-28 16:28:05 +0100298TIntermTyped *TIntermediate::AddSwizzle(TIntermTyped *baseExpression,
299 const TVectorFields &fields,
300 const TSourceLoc &dotLocation)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000301{
Olli Etuahob6fa0432016-09-28 16:28:05 +0100302 TVector<int> fieldsVector;
303 for (int i = 0; i < fields.num; ++i)
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700304 {
Olli Etuahob6fa0432016-09-28 16:28:05 +0100305 fieldsVector.push_back(fields.offsets[i]);
306 }
307 TIntermSwizzle *node = new TIntermSwizzle(baseExpression, fieldsVector);
308 node->setLine(dotLocation);
309
310 TIntermTyped *folded = node->fold();
311 if (folded)
312 {
313 return folded;
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000314 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000315
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000316 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000317}
318
319//
320// Create loop nodes.
321//
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500322TIntermNode *TIntermediate::addLoop(TLoopType type,
323 TIntermNode *init,
324 TIntermTyped *cond,
325 TIntermTyped *expr,
326 TIntermNode *body,
327 const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000328{
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100329 TIntermNode *node = new TIntermLoop(type, init, cond, expr, EnsureBlock(body));
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000330 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000331
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000332 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000333}
334
335//
336// Add branches.
337//
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500338TIntermBranch *TIntermediate::addBranch(TOperator branchOp, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000339{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000340 return addBranch(branchOp, 0, line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000341}
342
Jamie Madilld7b1ab52016-12-12 14:42:19 -0500343TIntermBranch *TIntermediate::addBranch(TOperator branchOp,
344 TIntermTyped *expression,
345 const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000346{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700347 TIntermBranch *node = new TIntermBranch(branchOp, expression);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000348 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000349
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000350 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000351}
352
Olli Etuahof119a262016-08-19 15:54:22 +0300353TIntermTyped *TIntermediate::foldAggregateBuiltIn(TIntermAggregate *aggregate,
354 TDiagnostics *diagnostics)
Arun Patole274f0702015-05-05 13:33:30 +0530355{
Olli Etuahob43846e2015-06-02 18:18:57 +0300356 switch (aggregate->getOp())
Arun Patole274f0702015-05-05 13:33:30 +0530357 {
Olli Etuaho1d122782015-11-06 15:35:17 +0200358 case EOpAtan:
359 case EOpPow:
360 case EOpMod:
361 case EOpMin:
362 case EOpMax:
363 case EOpClamp:
364 case EOpMix:
365 case EOpStep:
366 case EOpSmoothStep:
Olli Etuahoe1805592017-01-02 16:41:20 +0000367 case EOpMulMatrixComponentWise:
Olli Etuaho1d122782015-11-06 15:35:17 +0200368 case EOpOuterProduct:
Olli Etuahoe1805592017-01-02 16:41:20 +0000369 case EOpEqualComponentWise:
370 case EOpNotEqualComponentWise:
371 case EOpLessThanComponentWise:
372 case EOpLessThanEqualComponentWise:
373 case EOpGreaterThanComponentWise:
374 case EOpGreaterThanEqualComponentWise:
Olli Etuaho1d122782015-11-06 15:35:17 +0200375 case EOpDistance:
376 case EOpDot:
377 case EOpCross:
378 case EOpFaceForward:
379 case EOpReflect:
380 case EOpRefract:
Olli Etuahof119a262016-08-19 15:54:22 +0300381 return aggregate->fold(diagnostics);
Olli Etuaho1d122782015-11-06 15:35:17 +0200382 default:
383 // TODO: Add support for folding array constructors
384 if (aggregate->isConstructor() && !aggregate->isArray())
385 {
Olli Etuahof119a262016-08-19 15:54:22 +0300386 return aggregate->fold(diagnostics);
Olli Etuaho1d122782015-11-06 15:35:17 +0200387 }
388 // Constant folding not supported for the built-in.
389 return nullptr;
Arun Patole274f0702015-05-05 13:33:30 +0530390 }
Arun Patole274f0702015-05-05 13:33:30 +0530391}
Jamie Madill45bcc782016-11-07 13:58:48 -0500392
393} // namespace sh