blob: bb75d9a2e8af5326f303c1f9e96e4491c74e34b3 [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
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000018////////////////////////////////////////////////////////////////////////////
19//
20// First set of functions are to help build the intermediate representation.
21// These functions are not member functions of the nodes.
22// They are called from parser productions.
23//
24/////////////////////////////////////////////////////////////////////////////
25
26//
27// Add a terminal node for an identifier in an expression.
28//
29// Returns the added node.
30//
Zhenyao Moe40d1e92014-07-16 17:40:36 -070031TIntermSymbol *TIntermediate::addSymbol(
32 int id, const TString &name, const TType &type, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000033{
Zhenyao Moe40d1e92014-07-16 17:40:36 -070034 TIntermSymbol *node = new TIntermSymbol(id, name, type);
alokp@chromium.org2cf17712010-03-30 20:33:18 +000035 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000036
alokp@chromium.org2cf17712010-03-30 20:33:18 +000037 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000038}
39
40//
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000041// Connect two nodes through an index operator, where the left node is the base
42// of an array or struct, and the right node is a direct or indirect offset.
43//
44// Returns the added node.
45// The caller should set the type of the returned node.
46//
Olli Etuaho3272a6d2016-08-29 17:54:50 +030047TIntermTyped *TIntermediate::addIndex(TOperator op,
48 TIntermTyped *base,
49 TIntermTyped *index,
50 const TSourceLoc &line,
51 TDiagnostics *diagnostics)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000052{
Olli Etuaho3272a6d2016-08-29 17:54:50 +030053 TIntermBinary *node = new TIntermBinary(op, base, index);
alokp@chromium.org2cf17712010-03-30 20:33:18 +000054 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000055
Olli Etuaho3272a6d2016-08-29 17:54:50 +030056 TIntermTyped *folded = node->fold(diagnostics);
57 if (folded)
58 {
59 return folded;
60 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000061
alokp@chromium.org2cf17712010-03-30 20:33:18 +000062 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000063}
64
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000065// This is the safe way to change the operator on an aggregate, as it
66// does lots of error checking and fixing. Especially for establishing
Olli Etuaho6d40bbd2016-09-30 13:49:38 +010067// a function call's operation on it's set of parameters.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000068//
69// Returns an aggregate node, which could be the one passed in if
daniel@transgaming.com978702d2012-04-04 15:05:58 +000070// it was already an aggregate but no operator was set.
Zhenyao Moe40d1e92014-07-16 17:40:36 -070071TIntermAggregate *TIntermediate::setAggregateOperator(
72 TIntermNode *node, TOperator op, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000073{
Zhenyao Moe40d1e92014-07-16 17:40:36 -070074 TIntermAggregate *aggNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000075
alokp@chromium.org2cf17712010-03-30 20:33:18 +000076 //
77 // Make sure we have an aggregate. If not turn it into one.
78 //
Zhenyao Moe40d1e92014-07-16 17:40:36 -070079 if (node)
80 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +000081 aggNode = node->getAsAggregate();
Zhenyao Moe40d1e92014-07-16 17:40:36 -070082 if (aggNode == NULL || aggNode->getOp() != EOpNull)
83 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +000084 //
85 // Make an aggregate containing this node.
86 //
87 aggNode = new TIntermAggregate();
Zhenyao Moe40d1e92014-07-16 17:40:36 -070088 aggNode->getSequence()->push_back(node);
alokp@chromium.org2cf17712010-03-30 20:33:18 +000089 }
Zhenyao Moe40d1e92014-07-16 17:40:36 -070090 }
91 else
92 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +000093 aggNode = new TIntermAggregate();
Zhenyao Moe40d1e92014-07-16 17:40:36 -070094 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000095
alokp@chromium.org2cf17712010-03-30 20:33:18 +000096 //
97 // Set the operator.
98 //
alokp@chromium.org58e54292010-08-24 21:40:03 +000099 aggNode->setOp(op);
Jamie Madill075edd82013-07-08 13:30:19 -0400100 aggNode->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000101
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000102 return aggNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000103}
104
105//
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000106// Safe way to combine two nodes into an aggregate. Works with null pointers,
107// a node that's not a aggregate yet, etc.
108//
109// Returns the resulting aggregate, unless 0 was passed in for
110// both existing nodes.
111//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700112TIntermAggregate *TIntermediate::growAggregate(
113 TIntermNode *left, TIntermNode *right, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000114{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700115 if (left == NULL && right == NULL)
116 return NULL;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000117
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700118 TIntermAggregate *aggNode = NULL;
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000119 if (left)
120 aggNode = left->getAsAggregate();
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700121 if (!aggNode || aggNode->getOp() != EOpNull)
122 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000123 aggNode = new TIntermAggregate;
124 if (left)
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700125 aggNode->getSequence()->push_back(left);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000126 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000127
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000128 if (right)
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700129 aggNode->getSequence()->push_back(right);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000130
Jamie Madill075edd82013-07-08 13:30:19 -0400131 aggNode->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000132
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000133 return aggNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000134}
135
136//
137// Turn an existing node into an aggregate.
138//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700139// Returns an aggregate, unless NULL was passed in for the existing node.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000140//
Olli Etuaho32db19b2016-10-04 14:43:16 +0100141TIntermAggregate *TIntermediate::MakeAggregate(TIntermNode *node, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000142{
Olli Etuaho32db19b2016-10-04 14:43:16 +0100143 if (node == nullptr)
144 return nullptr;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000145
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700146 TIntermAggregate *aggNode = new TIntermAggregate;
147 aggNode->getSequence()->push_back(node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000148
Jamie Madill075edd82013-07-08 13:30:19 -0400149 aggNode->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000150
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000151 return aggNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000152}
153
Olli Etuaho7d7f8c42015-05-19 18:38:49 +0300154// If the input node is nullptr, return nullptr.
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100155// If the input node is a block node, return it.
156// If the input node is not a block node, put it inside a block node and return that.
157TIntermBlock *TIntermediate::EnsureBlock(TIntermNode *node)
Olli Etuaho7d7f8c42015-05-19 18:38:49 +0300158{
159 if (node == nullptr)
160 return nullptr;
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100161 TIntermBlock *blockNode = node->getAsBlock();
162 if (blockNode != nullptr)
163 return blockNode;
Olli Etuaho7d7f8c42015-05-19 18:38:49 +0300164
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100165 blockNode = new TIntermBlock();
166 blockNode->setLine(node->getLine());
167 blockNode->getSequence()->push_back(node);
168 return blockNode;
Olli Etuaho7d7f8c42015-05-19 18:38:49 +0300169}
170
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000171// For "if" test nodes. There are three children; a condition,
172// a true path, and a false path. The two paths are in the
173// nodePair.
174//
Olli Etuaho57961272016-09-14 13:57:46 +0300175// Returns the node created.
176TIntermNode *TIntermediate::addIfElse(TIntermTyped *cond,
177 TIntermNodePair nodePair,
178 const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000179{
Olli Etuaho57961272016-09-14 13:57:46 +0300180 // For compile time constant conditions, prune the code now.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000181
Olli Etuaho7c3848e2015-11-04 13:19:17 +0200182 if (cond->getAsConstantUnion())
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700183 {
shannon.woods%transgaming.com@gtempaccount.comc0d0c222013-04-13 03:29:36 +0000184 if (cond->getAsConstantUnion()->getBConst(0) == true)
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700185 {
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100186 return EnsureBlock(nodePair.node1);
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700187 }
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000188 else
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700189 {
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100190 return EnsureBlock(nodePair.node2);
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700191 }
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000192 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000193
Olli Etuaho57961272016-09-14 13:57:46 +0300194 TIntermIfElse *node =
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100195 new TIntermIfElse(cond, EnsureBlock(nodePair.node1), EnsureBlock(nodePair.node2));
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000196 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000197
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000198 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000199}
200
Olli Etuaho15200042015-11-04 16:56:31 +0200201TIntermTyped *TIntermediate::addComma(TIntermTyped *left,
202 TIntermTyped *right,
203 const TSourceLoc &line,
204 int shaderVersion)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000205{
Olli Etuaho15200042015-11-04 16:56:31 +0200206 TQualifier resultQualifier = EvqConst;
207 // ESSL3.00 section 12.43: The result of a sequence operator is not a constant-expression.
208 if (shaderVersion >= 300 || left->getQualifier() != EvqConst ||
209 right->getQualifier() != EvqConst)
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700210 {
Olli Etuaho15200042015-11-04 16:56:31 +0200211 resultQualifier = EvqTemporary;
212 }
213
214 TIntermTyped *commaNode = nullptr;
215 if (!left->hasSideEffects())
216 {
217 commaNode = right;
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700218 }
219 else
220 {
Olli Etuaho15200042015-11-04 16:56:31 +0200221 commaNode = growAggregate(left, right, line);
222 commaNode->getAsAggregate()->setOp(EOpComma);
223 commaNode->setType(right->getType());
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000224 }
Olli Etuaho15200042015-11-04 16:56:31 +0200225 commaNode->getTypePointer()->setQualifier(resultQualifier);
226 return commaNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000227}
228
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000229// For "?:" test nodes. There are three children; a condition,
230// a true path, and a false path. The two paths are specified
231// as separate parameters.
232//
Olli Etuahod0bad2c2016-09-09 18:01:16 +0300233// Returns the ternary node created, or one of trueExpression and falseExpression if the expression
234// could be folded.
235TIntermTyped *TIntermediate::AddTernarySelection(TIntermTyped *cond,
236 TIntermTyped *trueExpression,
237 TIntermTyped *falseExpression,
238 const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000239{
Olli Etuaho7c3848e2015-11-04 13:19:17 +0200240 // Note that the node resulting from here can be a constant union without being qualified as
241 // constant.
242 if (cond->getAsConstantUnion())
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700243 {
Olli Etuahod0bad2c2016-09-09 18:01:16 +0300244 TQualifier resultQualifier =
245 TIntermTernary::DetermineQualifier(cond, trueExpression, falseExpression);
shannon.woods%transgaming.com@gtempaccount.comc0d0c222013-04-13 03:29:36 +0000246 if (cond->getAsConstantUnion()->getBConst(0))
Olli Etuaho7c3848e2015-11-04 13:19:17 +0200247 {
Olli Etuahod0bad2c2016-09-09 18:01:16 +0300248 trueExpression->getTypePointer()->setQualifier(resultQualifier);
249 return trueExpression;
Olli Etuaho7c3848e2015-11-04 13:19:17 +0200250 }
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000251 else
Olli Etuaho7c3848e2015-11-04 13:19:17 +0200252 {
Olli Etuahod0bad2c2016-09-09 18:01:16 +0300253 falseExpression->getTypePointer()->setQualifier(resultQualifier);
254 return falseExpression;
Olli Etuaho7c3848e2015-11-04 13:19:17 +0200255 }
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000256 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000257
Olli Etuahod0bad2c2016-09-09 18:01:16 +0300258 // Make a ternary node.
259 TIntermTernary *node = new TIntermTernary(cond, trueExpression, falseExpression);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000260 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000261
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000262 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000263}
264
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100265TIntermSwitch *TIntermediate::addSwitch(TIntermTyped *init,
266 TIntermBlock *statementList,
267 const TSourceLoc &line)
Olli Etuahoa3a36662015-02-17 13:46:51 +0200268{
Olli Etuaho3c1dfb52015-02-20 11:34:03 +0200269 TIntermSwitch *node = new TIntermSwitch(init, statementList);
270 node->setLine(line);
271
272 return node;
Olli Etuahoa3a36662015-02-17 13:46:51 +0200273}
274
275TIntermCase *TIntermediate::addCase(
276 TIntermTyped *condition, const TSourceLoc &line)
277{
Olli Etuaho3c1dfb52015-02-20 11:34:03 +0200278 TIntermCase *node = new TIntermCase(condition);
279 node->setLine(line);
280
281 return node;
Olli Etuahoa3a36662015-02-17 13:46:51 +0200282}
283
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000284//
285// Constant terminal nodes. Has a union that contains bool, float or int constants
286//
287// Returns the constant union node created.
288//
289
Olli Etuaho5c0e0232015-11-11 15:55:59 +0200290TIntermConstantUnion *TIntermediate::addConstantUnion(const TConstantUnion *constantUnion,
291 const TType &type,
292 const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000293{
Jamie Madillb11e2482015-05-04 14:21:22 -0400294 TIntermConstantUnion *node = new TIntermConstantUnion(constantUnion, type);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000295 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000296
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000297 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000298}
299
Olli Etuahob6fa0432016-09-28 16:28:05 +0100300TIntermTyped *TIntermediate::AddSwizzle(TIntermTyped *baseExpression,
301 const TVectorFields &fields,
302 const TSourceLoc &dotLocation)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000303{
Olli Etuahob6fa0432016-09-28 16:28:05 +0100304 TVector<int> fieldsVector;
305 for (int i = 0; i < fields.num; ++i)
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700306 {
Olli Etuahob6fa0432016-09-28 16:28:05 +0100307 fieldsVector.push_back(fields.offsets[i]);
308 }
309 TIntermSwizzle *node = new TIntermSwizzle(baseExpression, fieldsVector);
310 node->setLine(dotLocation);
311
312 TIntermTyped *folded = node->fold();
313 if (folded)
314 {
315 return folded;
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000316 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000317
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000318 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000319}
320
321//
322// Create loop nodes.
323//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700324TIntermNode *TIntermediate::addLoop(
325 TLoopType type, TIntermNode *init, TIntermTyped *cond, TIntermTyped *expr,
326 TIntermNode *body, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000327{
Olli Etuaho6d40bbd2016-09-30 13:49:38 +0100328 TIntermNode *node = new TIntermLoop(type, init, cond, expr, EnsureBlock(body));
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000329 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000330
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000331 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000332}
333
334//
335// Add branches.
336//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700337TIntermBranch* TIntermediate::addBranch(
338 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
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700343TIntermBranch* TIntermediate::addBranch(
344 TOperator branchOp, TIntermTyped *expression, const TSourceLoc &line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000345{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700346 TIntermBranch *node = new TIntermBranch(branchOp, expression);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000347 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000348
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000349 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000350}
351
Olli Etuahof119a262016-08-19 15:54:22 +0300352TIntermTyped *TIntermediate::foldAggregateBuiltIn(TIntermAggregate *aggregate,
353 TDiagnostics *diagnostics)
Arun Patole274f0702015-05-05 13:33:30 +0530354{
Olli Etuahob43846e2015-06-02 18:18:57 +0300355 switch (aggregate->getOp())
Arun Patole274f0702015-05-05 13:33:30 +0530356 {
Olli Etuaho1d122782015-11-06 15:35:17 +0200357 case EOpAtan:
358 case EOpPow:
359 case EOpMod:
360 case EOpMin:
361 case EOpMax:
362 case EOpClamp:
363 case EOpMix:
364 case EOpStep:
365 case EOpSmoothStep:
366 case EOpMul:
367 case EOpOuterProduct:
368 case EOpLessThan:
369 case EOpLessThanEqual:
370 case EOpGreaterThan:
371 case EOpGreaterThanEqual:
372 case EOpVectorEqual:
373 case EOpVectorNotEqual:
374 case EOpDistance:
375 case EOpDot:
376 case EOpCross:
377 case EOpFaceForward:
378 case EOpReflect:
379 case EOpRefract:
Olli Etuahof119a262016-08-19 15:54:22 +0300380 return aggregate->fold(diagnostics);
Olli Etuaho1d122782015-11-06 15:35:17 +0200381 default:
382 // TODO: Add support for folding array constructors
383 if (aggregate->isConstructor() && !aggregate->isArray())
384 {
Olli Etuahof119a262016-08-19 15:54:22 +0300385 return aggregate->fold(diagnostics);
Olli Etuaho1d122782015-11-06 15:35:17 +0200386 }
387 // Constant folding not supported for the built-in.
388 return nullptr;
Arun Patole274f0702015-05-05 13:33:30 +0530389 }
Arun Patole274f0702015-05-05 13:33:30 +0530390}