blob: ef01c5a99c1c17d6aee519b73ae350192e6b8371 [file] [log] [blame]
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001//
2// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
3// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
daniel@transgaming.combbf56f72010-04-20 18:52:13 +00007#include "compiler/ParseHelper.h"
8
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00009#include <stdarg.h>
apatrick@chromium.org8187fa82010-06-15 22:09:28 +000010#include <stdio.h>
daniel@transgaming.combbf56f72010-04-20 18:52:13 +000011
12#include "compiler/osinclude.h"
13#include "compiler/InitializeParseContext.h"
14
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000015///////////////////////////////////////////////////////////////////////
16//
17// Sub- vector and matrix fields
18//
19////////////////////////////////////////////////////////////////////////
20
21//
22// Look at a '.' field selector string and change it into offsets
23// for a vector.
24//
25bool TParseContext::parseVectorFields(const TString& compString, int vecSize, TVectorFields& fields, int line)
26{
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +000027 fields.num = (int) compString.size();
28 if (fields.num > 4) {
29 error(line, "illegal vector field selection", compString.c_str(), "");
30 return false;
31 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000032
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +000033 enum {
34 exyzw,
35 ergba,
36 estpq,
37 } fieldSet[4];
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000038
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +000039 for (int i = 0; i < fields.num; ++i) {
40 switch (compString[i]) {
41 case 'x':
42 fields.offsets[i] = 0;
43 fieldSet[i] = exyzw;
44 break;
45 case 'r':
46 fields.offsets[i] = 0;
47 fieldSet[i] = ergba;
48 break;
49 case 's':
50 fields.offsets[i] = 0;
51 fieldSet[i] = estpq;
52 break;
53 case 'y':
54 fields.offsets[i] = 1;
55 fieldSet[i] = exyzw;
56 break;
57 case 'g':
58 fields.offsets[i] = 1;
59 fieldSet[i] = ergba;
60 break;
61 case 't':
62 fields.offsets[i] = 1;
63 fieldSet[i] = estpq;
64 break;
65 case 'z':
66 fields.offsets[i] = 2;
67 fieldSet[i] = exyzw;
68 break;
69 case 'b':
70 fields.offsets[i] = 2;
71 fieldSet[i] = ergba;
72 break;
73 case 'p':
74 fields.offsets[i] = 2;
75 fieldSet[i] = estpq;
76 break;
77
78 case 'w':
79 fields.offsets[i] = 3;
80 fieldSet[i] = exyzw;
81 break;
82 case 'a':
83 fields.offsets[i] = 3;
84 fieldSet[i] = ergba;
85 break;
86 case 'q':
87 fields.offsets[i] = 3;
88 fieldSet[i] = estpq;
89 break;
90 default:
91 error(line, "illegal vector field selection", compString.c_str(), "");
92 return false;
93 }
94 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000095
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +000096 for (int i = 0; i < fields.num; ++i) {
97 if (fields.offsets[i] >= vecSize) {
98 error(line, "vector field selection out of range", compString.c_str(), "");
99 return false;
100 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000101
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000102 if (i > 0) {
103 if (fieldSet[i] != fieldSet[i-1]) {
104 error(line, "illegal - vector component fields not from the same set", compString.c_str(), "");
105 return false;
106 }
107 }
108 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000109
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000110 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000111}
112
113
114//
115// Look at a '.' field selector string and change it into offsets
116// for a matrix.
117//
118bool TParseContext::parseMatrixFields(const TString& compString, int matSize, TMatrixFields& fields, int line)
119{
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000120 fields.wholeRow = false;
121 fields.wholeCol = false;
122 fields.row = -1;
123 fields.col = -1;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000124
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000125 if (compString.size() != 2) {
126 error(line, "illegal length of matrix field selection", compString.c_str(), "");
127 return false;
128 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000129
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000130 if (compString[0] == '_') {
131 if (compString[1] < '0' || compString[1] > '3') {
132 error(line, "illegal matrix field selection", compString.c_str(), "");
133 return false;
134 }
135 fields.wholeCol = true;
136 fields.col = compString[1] - '0';
137 } else if (compString[1] == '_') {
138 if (compString[0] < '0' || compString[0] > '3') {
139 error(line, "illegal matrix field selection", compString.c_str(), "");
140 return false;
141 }
142 fields.wholeRow = true;
143 fields.row = compString[0] - '0';
144 } else {
145 if (compString[0] < '0' || compString[0] > '3' ||
146 compString[1] < '0' || compString[1] > '3') {
147 error(line, "illegal matrix field selection", compString.c_str(), "");
148 return false;
149 }
150 fields.row = compString[0] - '0';
151 fields.col = compString[1] - '0';
152 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000153
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000154 if (fields.row >= matSize || fields.col >= matSize) {
155 error(line, "matrix field selection out of range", compString.c_str(), "");
156 return false;
157 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000158
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000159 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000160}
161
162///////////////////////////////////////////////////////////////////////
163//
164// Errors
165//
166////////////////////////////////////////////////////////////////////////
167
168//
169// Track whether errors have occurred.
170//
171void TParseContext::recover()
172{
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000173 recoveredFromError = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000174}
175
176//
177// Used by flex/bison to output all syntax and parsing errors.
178//
alokp@chromium.orgc54bf502010-07-22 16:49:09 +0000179void TParseContext::error(TSourceLoc nLine, const char *szReason, const char *szToken,
180 const char *szExtraInfoFormat, ...)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000181{
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000182 char szExtraInfo[400];
183 va_list marker;
alokp@chromium.orgff42c632010-05-10 15:14:30 +0000184
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000185 va_start(marker, szExtraInfoFormat);
alokp@chromium.orgff42c632010-05-10 15:14:30 +0000186
187 vsnprintf(szExtraInfo, sizeof(szExtraInfo), szExtraInfoFormat, marker);
188
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000189 /* VC++ format: file(linenum) : error #: 'token' : extrainfo */
190 infoSink.info.prefix(EPrefixError);
191 infoSink.info.location(nLine);
192 infoSink.info << "'" << szToken << "' : " << szReason << " " << szExtraInfo << "\n";
alokp@chromium.orgff42c632010-05-10 15:14:30 +0000193
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000194 va_end(marker);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000195
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000196 ++numErrors;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000197}
198
199//
200// Same error message for all places assignments don't work.
201//
202void TParseContext::assignError(int line, const char* op, TString left, TString right)
203{
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000204 error(line, "", op, "cannot convert from '%s' to '%s'",
205 right.c_str(), left.c_str());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000206}
207
208//
209// Same error message for all places unary operations don't work.
210//
211void TParseContext::unaryOpError(int line, const char* op, TString operand)
212{
213 error(line, " wrong operand type", op,
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000214 "no operation '%s' exists that takes an operand of type %s (or there is no acceptable conversion)",
215 op, operand.c_str());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000216}
217
218//
219// Same error message for all binary operations don't work.
220//
221void TParseContext::binaryOpError(int line, const char* op, TString left, TString right)
222{
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000223 error(line, " wrong operand types ", op,
224 "no operation '%s' exists that takes a left-hand operand of type '%s' and "
225 "a right operand of type '%s' (or there is no acceptable conversion)",
226 op, left.c_str(), right.c_str());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000227}
228
daniel@transgaming.coma5d76232010-05-17 09:58:47 +0000229bool TParseContext::precisionErrorCheck(int line, TPrecision precision, TBasicType type){
230 switch( type ){
231 case EbtFloat:
232 if( precision == EbpUndefined ){
233 error( line, "No precision specified for (float)", "", "" );
234 return true;
235 }
236 break;
237 case EbtInt:
238 if( precision == EbpUndefined ){
239 error( line, "No precision specified (int)", "", "" );
240 return true;
241 }
242 break;
243 }
244 return false;
245}
246
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000247//
248// Both test and if necessary, spit out an error, to see if the node is really
249// an l-value that can be operated on this way.
250//
251// Returns true if the was an error.
252//
253bool TParseContext::lValueErrorCheck(int line, const char* op, TIntermTyped* node)
254{
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000255 TIntermSymbol* symNode = node->getAsSymbolNode();
256 TIntermBinary* binaryNode = node->getAsBinaryNode();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000257
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000258 if (binaryNode) {
259 bool errorReturn;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000260
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000261 switch(binaryNode->getOp()) {
262 case EOpIndexDirect:
263 case EOpIndexIndirect:
264 case EOpIndexDirectStruct:
265 return lValueErrorCheck(line, op, binaryNode->getLeft());
266 case EOpVectorSwizzle:
267 errorReturn = lValueErrorCheck(line, op, binaryNode->getLeft());
268 if (!errorReturn) {
269 int offset[4] = {0,0,0,0};
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000270
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000271 TIntermTyped* rightNode = binaryNode->getRight();
272 TIntermAggregate *aggrNode = rightNode->getAsAggregate();
273
274 for (TIntermSequence::iterator p = aggrNode->getSequence().begin();
275 p != aggrNode->getSequence().end(); p++) {
276 int value = (*p)->getAsTyped()->getAsConstantUnion()->getUnionArrayPointer()->getIConst();
277 offset[value]++;
278 if (offset[value] > 1) {
279 error(line, " l-value of swizzle cannot have duplicate components", op, "", "");
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000280
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000281 return true;
282 }
283 }
284 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000285
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000286 return errorReturn;
287 default:
288 break;
289 }
290 error(line, " l-value required", op, "", "");
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000291
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000292 return true;
293 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000294
295
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000296 const char* symbol = 0;
297 if (symNode != 0)
298 symbol = symNode->getSymbol().c_str();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000299
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000300 const char* message = 0;
301 switch (node->getQualifier()) {
302 case EvqConst: message = "can't modify a const"; break;
303 case EvqConstReadOnly: message = "can't modify a const"; break;
304 case EvqAttribute: message = "can't modify an attribute"; break;
305 case EvqUniform: message = "can't modify a uniform"; break;
306 case EvqVaryingIn: message = "can't modify a varying"; break;
307 case EvqInput: message = "can't modify an input"; break;
308 case EvqFragCoord: message = "can't modify gl_FragCoord"; break;
309 case EvqFrontFacing: message = "can't modify gl_FrontFacing"; break;
310 case EvqPointCoord: message = "can't modify gl_PointCoord"; break;
311 default:
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000312
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000313 //
314 // Type that can't be written to?
315 //
316 switch (node->getBasicType()) {
317 case EbtSampler2D:
318 case EbtSamplerCube:
319 message = "can't modify a sampler";
320 break;
321 case EbtVoid:
322 message = "can't modify void";
323 break;
324 default:
325 break;
326 }
327 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000328
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000329 if (message == 0 && binaryNode == 0 && symNode == 0) {
330 error(line, " l-value required", op, "", "");
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000331
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000332 return true;
333 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000334
335
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000336 //
337 // Everything else is okay, no error.
338 //
339 if (message == 0)
340 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000341
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000342 //
343 // If we get here, we have an error and a message.
344 //
345 if (symNode)
346 error(line, " l-value required", op, "\"%s\" (%s)", symbol, message);
347 else
348 error(line, " l-value required", op, "(%s)", message);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000349
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000350 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000351}
352
353//
354// Both test, and if necessary spit out an error, to see if the node is really
355// a constant.
356//
357// Returns true if the was an error.
358//
359bool TParseContext::constErrorCheck(TIntermTyped* node)
360{
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000361 if (node->getQualifier() == EvqConst)
362 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000363
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000364 error(node->getLine(), "constant expression required", "", "");
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000365
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000366 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000367}
368
369//
370// Both test, and if necessary spit out an error, to see if the node is really
371// an integer.
372//
373// Returns true if the was an error.
374//
375bool TParseContext::integerErrorCheck(TIntermTyped* node, const char* token)
376{
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000377 if (node->getBasicType() == EbtInt && node->getNominalSize() == 1)
378 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000379
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000380 error(node->getLine(), "integer expression required", token, "");
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000381
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000382 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000383}
384
385//
386// Both test, and if necessary spit out an error, to see if we are currently
387// globally scoped.
388//
389// Returns true if the was an error.
390//
391bool TParseContext::globalErrorCheck(int line, bool global, const char* token)
392{
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000393 if (global)
394 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000395
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000396 error(line, "only allowed at global scope", token, "");
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000397
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000398 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000399}
400
401//
402// For now, keep it simple: if it starts "gl_", it's reserved, independent
403// of scope. Except, if the symbol table is at the built-in push-level,
404// which is when we are parsing built-ins.
alokp@chromium.org613ef312010-07-21 18:54:22 +0000405// Also checks for "webgl_" and "_webgl_" reserved identifiers if parsing a
406// webgl shader.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000407//
408// Returns true if there was an error.
409//
410bool TParseContext::reservedErrorCheck(int line, const TString& identifier)
411{
alokp@chromium.org613ef312010-07-21 18:54:22 +0000412 static const char* reservedErrMsg = "reserved built-in name";
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000413 if (!symbolTable.atBuiltInLevel()) {
414 if (identifier.substr(0, 3) == TString("gl_")) {
alokp@chromium.org613ef312010-07-21 18:54:22 +0000415 error(line, reservedErrMsg, "gl_", "");
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000416 return true;
417 }
alokp@chromium.org613ef312010-07-21 18:54:22 +0000418 if (spec == EShSpecWebGL) {
419 if (identifier.substr(0, 6) == TString("webgl_")) {
420 error(line, reservedErrMsg, "webgl_", "");
421 return true;
422 }
423 if (identifier.substr(0, 7) == TString("_webgl_")) {
424 error(line, reservedErrMsg, "_webgl_", "");
425 return true;
426 }
427 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000428 if (identifier.find("__") != TString::npos) {
429 //error(line, "Two consecutive underscores are reserved for future use.", identifier.c_str(), "", "");
430 //return true;
431 infoSink.info.message(EPrefixWarning, "Two consecutive underscores are reserved for future use.", line);
432 return false;
433 }
434 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000435
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000436 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000437}
438
439//
440// Make sure there is enough data provided to the constructor to build
441// something of the type of the constructor. Also returns the type of
442// the constructor.
443//
444// Returns true if there was an error in construction.
445//
446bool TParseContext::constructorErrorCheck(int line, TIntermNode* node, TFunction& function, TOperator op, TType* type)
447{
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000448 *type = function.getReturnType();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000449
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000450 bool constructingMatrix = false;
451 switch(op) {
452 case EOpConstructMat2:
453 case EOpConstructMat3:
454 case EOpConstructMat4:
455 constructingMatrix = true;
456 break;
457 default:
458 break;
459 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000460
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000461 //
462 // Note: It's okay to have too many components available, but not okay to have unused
463 // arguments. 'full' will go to true when enough args have been seen. If we loop
464 // again, there is an extra argument, so 'overfull' will become true.
465 //
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000466
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000467 int size = 0;
468 bool constType = true;
469 bool full = false;
470 bool overFull = false;
471 bool matrixInMatrix = false;
472 bool arrayArg = false;
473 for (int i = 0; i < function.getParamCount(); ++i) {
alokp@chromium.orgb19403a2010-09-08 17:56:26 +0000474 const TParameter& param = function.getParam(i);
475 size += param.type->getObjectSize();
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000476
alokp@chromium.orgb19403a2010-09-08 17:56:26 +0000477 if (constructingMatrix && param.type->isMatrix())
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000478 matrixInMatrix = true;
479 if (full)
480 overFull = true;
481 if (op != EOpConstructStruct && !type->isArray() && size >= type->getObjectSize())
482 full = true;
alokp@chromium.orgb19403a2010-09-08 17:56:26 +0000483 if (param.type->getQualifier() != EvqConst)
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000484 constType = false;
alokp@chromium.orgb19403a2010-09-08 17:56:26 +0000485 if (param.type->isArray())
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000486 arrayArg = true;
487 }
488
489 if (constType)
alokp@chromium.org58e54292010-08-24 21:40:03 +0000490 type->setQualifier(EvqConst);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000491
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000492 if (type->isArray() && type->getArraySize() != function.getParamCount()) {
493 error(line, "array constructor needs one argument per array element", "constructor", "");
494 return true;
495 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000496
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000497 if (arrayArg && op != EOpConstructStruct) {
498 error(line, "constructing from a non-dereferenced array", "constructor", "");
499 return true;
500 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000501
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000502 if (matrixInMatrix && !type->isArray()) {
daniel@transgaming.combef0b6d2010-04-29 03:32:39 +0000503 if (function.getParamCount() != 1) {
504 error(line, "constructing matrix from matrix can only take one argument", "constructor", "");
505 return true;
506 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000507 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000508
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000509 if (overFull) {
510 error(line, "too many arguments", "constructor", "");
511 return true;
512 }
513
514 if (op == EOpConstructStruct && !type->isArray() && type->getStruct()->size() != function.getParamCount()) {
515 error(line, "Number of constructor parameters does not match the number of structure fields", "constructor", "");
516 return true;
517 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000518
daniel@transgaming.combef0b6d2010-04-29 03:32:39 +0000519 if (!type->isMatrix()) {
520 if ((op != EOpConstructStruct && size != 1 && size < type->getObjectSize()) ||
521 (op == EOpConstructStruct && size < type->getObjectSize())) {
522 error(line, "not enough data provided for construction", "constructor", "");
523 return true;
524 }
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000525 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000526
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000527 TIntermTyped* typed = node->getAsTyped();
528 if (typed == 0) {
529 error(line, "constructor argument does not have a type", "constructor", "");
530 return true;
531 }
532 if (op != EOpConstructStruct && IsSampler(typed->getBasicType())) {
533 error(line, "cannot convert a sampler", "constructor", "");
534 return true;
535 }
536 if (typed->getBasicType() == EbtVoid) {
537 error(line, "cannot convert a void", "constructor", "");
538 return true;
539 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000540
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000541 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000542}
543
544// This function checks to see if a void variable has been declared and raise an error message for such a case
545//
546// returns true in case of an error
547//
548bool TParseContext::voidErrorCheck(int line, const TString& identifier, const TPublicType& pubType)
549{
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000550 if (pubType.type == EbtVoid) {
551 error(line, "illegal use of type 'void'", identifier.c_str(), "");
552 return true;
553 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000554
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000555 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000556}
557
558// This function checks to see if the node (for the expression) contains a scalar boolean expression or not
559//
560// returns true in case of an error
561//
562bool TParseContext::boolErrorCheck(int line, const TIntermTyped* type)
563{
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000564 if (type->getBasicType() != EbtBool || type->isArray() || type->isMatrix() || type->isVector()) {
565 error(line, "boolean expression expected", "", "");
566 return true;
567 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000568
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000569 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000570}
571
572// This function checks to see if the node (for the expression) contains a scalar boolean expression or not
573//
574// returns true in case of an error
575//
576bool TParseContext::boolErrorCheck(int line, const TPublicType& pType)
577{
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000578 if (pType.type != EbtBool || pType.array || pType.matrix || (pType.size > 1)) {
579 error(line, "boolean expression expected", "", "");
580 return true;
581 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000582
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000583 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000584}
585
586bool TParseContext::samplerErrorCheck(int line, const TPublicType& pType, const char* reason)
587{
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000588 if (pType.type == EbtStruct) {
589 if (containsSampler(*pType.userDef)) {
alokp@chromium.org58e54292010-08-24 21:40:03 +0000590 error(line, reason, getBasicString(pType.type), "(structure contains a sampler)");
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000591
592 return true;
593 }
594
595 return false;
596 } else if (IsSampler(pType.type)) {
alokp@chromium.org58e54292010-08-24 21:40:03 +0000597 error(line, reason, getBasicString(pType.type), "");
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000598
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000599 return true;
600 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000601
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000602 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000603}
604
605bool TParseContext::structQualifierErrorCheck(int line, const TPublicType& pType)
606{
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000607 if ((pType.qualifier == EvqVaryingIn || pType.qualifier == EvqVaryingOut || pType.qualifier == EvqAttribute) &&
608 pType.type == EbtStruct) {
609 error(line, "cannot be used with a structure", getQualifierString(pType.qualifier), "");
610
611 return true;
612 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000613
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000614 if (pType.qualifier != EvqUniform && samplerErrorCheck(line, pType, "samplers must be uniform"))
615 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000616
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000617 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000618}
619
620bool TParseContext::parameterSamplerErrorCheck(int line, TQualifier qualifier, const TType& type)
621{
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000622 if ((qualifier == EvqOut || qualifier == EvqInOut) &&
623 type.getBasicType() != EbtStruct && IsSampler(type.getBasicType())) {
624 error(line, "samplers cannot be output parameters", type.getBasicString(), "");
625 return true;
626 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000627
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000628 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000629}
630
631bool TParseContext::containsSampler(TType& type)
632{
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000633 if (IsSampler(type.getBasicType()))
634 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000635
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000636 if (type.getBasicType() == EbtStruct) {
637 TTypeList& structure = *type.getStruct();
638 for (unsigned int i = 0; i < structure.size(); ++i) {
639 if (containsSampler(*structure[i].type))
640 return true;
641 }
642 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000643
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000644 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000645}
646
647//
648// Do size checking for an array type's size.
649//
650// Returns true if there was an error.
651//
652bool TParseContext::arraySizeErrorCheck(int line, TIntermTyped* expr, int& size)
653{
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000654 TIntermConstantUnion* constant = expr->getAsConstantUnion();
655 if (constant == 0 || constant->getBasicType() != EbtInt) {
656 error(line, "array size must be a constant integer expression", "", "");
657 return true;
658 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000659
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000660 size = constant->getUnionArrayPointer()->getIConst();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000661
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000662 if (size <= 0) {
663 error(line, "array size must be a positive integer", "", "");
664 size = 1;
665 return true;
666 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000667
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000668 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000669}
670
671//
672// See if this qualifier can be an array.
673//
674// Returns true if there is an error.
675//
676bool TParseContext::arrayQualifierErrorCheck(int line, TPublicType type)
677{
alokp@chromium.org8f0f24a2010-09-01 21:06:24 +0000678 if ((type.qualifier == EvqAttribute) || (type.qualifier == EvqConst)) {
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000679 error(line, "cannot declare arrays of this qualifier", TType(type).getCompleteString().c_str(), "");
680 return true;
681 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000682
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000683 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000684}
685
686//
687// See if this type can be an array.
688//
689// Returns true if there is an error.
690//
691bool TParseContext::arrayTypeErrorCheck(int line, TPublicType type)
692{
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000693 //
694 // Can the type be an array?
695 //
696 if (type.array) {
697 error(line, "cannot declare arrays of arrays", TType(type).getCompleteString().c_str(), "");
698 return true;
699 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000700
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000701 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000702}
703
704//
705// Do all the semantic checking for declaring an array, with and
706// without a size, and make the right changes to the symbol table.
707//
708// size == 0 means no specified size.
709//
710// Returns true if there was an error.
711//
712bool TParseContext::arrayErrorCheck(int line, TString& identifier, TPublicType type, TVariable*& variable)
713{
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000714 //
715 // Don't check for reserved word use until after we know it's not in the symbol table,
716 // because reserved arrays can be redeclared.
717 //
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000718
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000719 bool builtIn = false;
720 bool sameScope = false;
721 TSymbol* symbol = symbolTable.find(identifier, &builtIn, &sameScope);
722 if (symbol == 0 || !sameScope) {
723 if (reservedErrorCheck(line, identifier))
724 return true;
725
726 variable = new TVariable(&identifier, TType(type));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000727
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000728 if (type.arraySize)
729 variable->getType().setArraySize(type.arraySize);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000730
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000731 if (! symbolTable.insert(*variable)) {
732 delete variable;
733 error(line, "INTERNAL ERROR inserting new symbol", identifier.c_str(), "");
734 return true;
735 }
736 } else {
737 if (! symbol->isVariable()) {
738 error(line, "variable expected", identifier.c_str(), "");
739 return true;
740 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000741
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000742 variable = static_cast<TVariable*>(symbol);
743 if (! variable->getType().isArray()) {
744 error(line, "redeclaring non-array as array", identifier.c_str(), "");
745 return true;
746 }
747 if (variable->getType().getArraySize() > 0) {
748 error(line, "redeclaration of array with size", identifier.c_str(), "");
749 return true;
750 }
751
752 if (! variable->getType().sameElementType(TType(type))) {
753 error(line, "redeclaration of array with a different type", identifier.c_str(), "");
754 return true;
755 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000756
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000757 TType* t = variable->getArrayInformationType();
758 while (t != 0) {
759 if (t->getMaxArraySize() > type.arraySize) {
760 error(line, "higher index value already used for the array", identifier.c_str(), "");
761 return true;
762 }
763 t->setArraySize(type.arraySize);
764 t = t->getArrayInformationType();
765 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000766
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000767 if (type.arraySize)
768 variable->getType().setArraySize(type.arraySize);
769 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000770
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000771 if (voidErrorCheck(line, identifier, type))
772 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000773
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000774 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000775}
776
777bool TParseContext::arraySetMaxSize(TIntermSymbol *node, TType* type, int size, bool updateFlag, TSourceLoc line)
778{
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000779 bool builtIn = false;
780 TSymbol* symbol = symbolTable.find(node->getSymbol(), &builtIn);
781 if (symbol == 0) {
782 error(line, " undeclared identifier", node->getSymbol().c_str(), "");
783 return true;
784 }
785 TVariable* variable = static_cast<TVariable*>(symbol);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000786
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000787 type->setArrayInformationType(variable->getArrayInformationType());
788 variable->updateArrayInformationType(type);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000789
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000790 // special casing to test index value of gl_FragData. If the accessed index is >= gl_MaxDrawBuffers
791 // its an error
792 if (node->getSymbol() == "gl_FragData") {
793 TSymbol* fragData = symbolTable.find("gl_MaxDrawBuffers", &builtIn);
794 if (fragData == 0) {
795 infoSink.info.message(EPrefixInternalError, "gl_MaxDrawBuffers not defined", line);
796 return true;
797 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000798
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000799 int fragDataValue = static_cast<TVariable*>(fragData)->getConstPointer()[0].getIConst();
800 if (fragDataValue <= size) {
801 error(line, "", "[", "gl_FragData can only have a max array size of up to gl_MaxDrawBuffers", "");
802 return true;
803 }
804 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000805
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000806 // we dont want to update the maxArraySize when this flag is not set, we just want to include this
807 // node type in the chain of node types so that its updated when a higher maxArraySize comes in.
808 if (!updateFlag)
809 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000810
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000811 size++;
812 variable->getType().setMaxArraySize(size);
813 type->setMaxArraySize(size);
814 TType* tt = type;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000815
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000816 while(tt->getArrayInformationType() != 0) {
817 tt = tt->getArrayInformationType();
818 tt->setMaxArraySize(size);
819 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000820
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000821 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000822}
823
824//
825// Enforce non-initializer type/qualifier rules.
826//
827// Returns true if there was an error.
828//
829bool TParseContext::nonInitConstErrorCheck(int line, TString& identifier, TPublicType& type)
830{
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000831 //
832 // Make the qualifier make sense.
833 //
834 if (type.qualifier == EvqConst) {
835 type.qualifier = EvqTemporary;
836 error(line, "variables with qualifier 'const' must be initialized", identifier.c_str(), "");
837 return true;
838 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000839
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000840 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000841}
842
843//
844// Do semantic checking for a variable declaration that has no initializer,
845// and update the symbol table.
846//
847// Returns true if there was an error.
848//
849bool TParseContext::nonInitErrorCheck(int line, TString& identifier, TPublicType& type)
850{
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000851 if (reservedErrorCheck(line, identifier))
852 recover();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000853
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000854 TVariable* variable = new TVariable(&identifier, TType(type));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000855
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000856 if (! symbolTable.insert(*variable)) {
857 error(line, "redefinition", variable->getName().c_str(), "");
858 delete variable;
859 return true;
860 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000861
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000862 if (voidErrorCheck(line, identifier, type))
863 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000864
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000865 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000866}
867
868bool TParseContext::paramErrorCheck(int line, TQualifier qualifier, TQualifier paramQualifier, TType* type)
869{
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000870 if (qualifier != EvqConst && qualifier != EvqTemporary) {
871 error(line, "qualifier not allowed on function parameter", getQualifierString(qualifier), "");
872 return true;
873 }
874 if (qualifier == EvqConst && paramQualifier != EvqIn) {
875 error(line, "qualifier not allowed with ", getQualifierString(qualifier), getQualifierString(paramQualifier));
876 return true;
877 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000878
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000879 if (qualifier == EvqConst)
alokp@chromium.org58e54292010-08-24 21:40:03 +0000880 type->setQualifier(EvqConstReadOnly);
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000881 else
alokp@chromium.org58e54292010-08-24 21:40:03 +0000882 type->setQualifier(paramQualifier);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000883
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000884 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000885}
886
alokp@chromium.org8815d7f2010-09-09 17:30:03 +0000887bool TParseContext::extensionErrorCheck(int line, const TString& extension)
888{
889 TExtensionBehavior::const_iterator iter = extensionBehavior.find(extension);
890 if (iter == extensionBehavior.end()) {
891 error(line, "extension", extension.c_str(), "is not supported");
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000892 return true;
893 }
alokp@chromium.org8815d7f2010-09-09 17:30:03 +0000894 if (iter->second == EBhDisable) {
895 error(line, "extension", extension.c_str(), "is disabled");
896 return true;
897 }
898 if (iter->second == EBhWarn) {
899 TString msg = "extension " + extension + " is being used";
900 infoSink.info.message(EPrefixWarning, msg.c_str(), line);
901 return false;
902 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000903
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000904 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000905}
906
907/////////////////////////////////////////////////////////////////////////////////
908//
909// Non-Errors.
910//
911/////////////////////////////////////////////////////////////////////////////////
912
913//
914// Look up a function name in the symbol table, and make sure it is a function.
915//
916// Return the function symbol if found, otherwise 0.
917//
918const TFunction* TParseContext::findFunction(int line, TFunction* call, bool *builtIn)
919{
alokp@chromium.org0a576182010-08-09 17:16:27 +0000920 // First find by unmangled name to check whether the function name has been
921 // hidden by a variable name or struct typename.
922 const TSymbol* symbol = symbolTable.find(call->getName(), builtIn);
923 if (symbol == 0) {
924 symbol = symbolTable.find(call->getMangledName(), builtIn);
925 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000926
alokp@chromium.org0a576182010-08-09 17:16:27 +0000927 if (symbol == 0) {
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000928 error(line, "no matching overloaded function found", call->getName().c_str(), "");
929 return 0;
930 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000931
alokp@chromium.org0a576182010-08-09 17:16:27 +0000932 if (!symbol->isFunction()) {
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000933 error(line, "function name expected", call->getName().c_str(), "");
934 return 0;
935 }
alokp@chromium.org0a576182010-08-09 17:16:27 +0000936
937 return static_cast<const TFunction*>(symbol);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000938}
939
940//
941// Initializers show up in several places in the grammar. Have one set of
942// code to handle them here.
943//
944bool TParseContext::executeInitializer(TSourceLoc line, TString& identifier, TPublicType& pType,
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000945 TIntermTyped* initializer, TIntermNode*& intermNode, TVariable* variable)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000946{
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000947 TType type = TType(pType);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000948
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000949 if (variable == 0) {
950 if (reservedErrorCheck(line, identifier))
951 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000952
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000953 if (voidErrorCheck(line, identifier, pType))
954 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000955
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000956 //
957 // add variable to symbol table
958 //
959 variable = new TVariable(&identifier, type);
960 if (! symbolTable.insert(*variable)) {
961 error(line, "redefinition", variable->getName().c_str(), "");
962 return true;
963 // don't delete variable, it's used by error recovery, and the pool
964 // pop will take care of the memory
965 }
966 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000967
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000968 //
969 // identifier must be of type constant, a global, or a temporary
970 //
971 TQualifier qualifier = variable->getType().getQualifier();
972 if ((qualifier != EvqTemporary) && (qualifier != EvqGlobal) && (qualifier != EvqConst)) {
973 error(line, " cannot initialize this type of qualifier ", variable->getType().getQualifierString(), "");
974 return true;
975 }
976 //
977 // test for and propagate constant
978 //
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000979
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000980 if (qualifier == EvqConst) {
981 if (qualifier != initializer->getType().getQualifier()) {
982 error(line, " assigning non-constant to", "=", "'%s'", variable->getType().getCompleteString().c_str());
alokp@chromium.org58e54292010-08-24 21:40:03 +0000983 variable->getType().setQualifier(EvqTemporary);
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000984 return true;
985 }
986 if (type != initializer->getType()) {
987 error(line, " non-matching types for const initializer ",
988 variable->getType().getQualifierString(), "");
alokp@chromium.org58e54292010-08-24 21:40:03 +0000989 variable->getType().setQualifier(EvqTemporary);
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000990 return true;
991 }
992 if (initializer->getAsConstantUnion()) {
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +0000993 ConstantUnion* unionArray = variable->getConstPointer();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000994
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +0000995 if (type.getObjectSize() == 1 && type.getBasicType() != EbtStruct) {
996 *unionArray = (initializer->getAsConstantUnion()->getUnionArrayPointer())[0];
997 } else {
998 variable->shareConstPointer(initializer->getAsConstantUnion()->getUnionArrayPointer());
999 }
1000 } else if (initializer->getAsSymbolNode()) {
1001 const TSymbol* symbol = symbolTable.find(initializer->getAsSymbolNode()->getSymbol());
1002 const TVariable* tVar = static_cast<const TVariable*>(symbol);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001003
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001004 ConstantUnion* constArray = tVar->getConstPointer();
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001005 variable->shareConstPointer(constArray);
1006 } else {
1007 error(line, " cannot assign to", "=", "'%s'", variable->getType().getCompleteString().c_str());
alokp@chromium.org58e54292010-08-24 21:40:03 +00001008 variable->getType().setQualifier(EvqTemporary);
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001009 return true;
1010 }
1011 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001012
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001013 if (qualifier != EvqConst) {
1014 TIntermSymbol* intermSymbol = intermediate.addSymbol(variable->getUniqueId(), variable->getName(), variable->getType(), line);
1015 intermNode = intermediate.addAssign(EOpInitialize, intermSymbol, initializer, line);
1016 if (intermNode == 0) {
1017 assignError(line, "=", intermSymbol->getCompleteString(), initializer->getCompleteString());
1018 return true;
1019 }
1020 } else
1021 intermNode = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001022
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001023 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001024}
1025
1026bool TParseContext::areAllChildConst(TIntermAggregate* aggrNode)
1027{
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001028 if (!aggrNode->isConstructor())
1029 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001030
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001031 bool allConstant = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001032
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001033 // check if all the child nodes are constants so that they can be inserted into
1034 // the parent node
1035 if (aggrNode) {
1036 TIntermSequence &childSequenceVector = aggrNode->getSequence() ;
1037 for (TIntermSequence::iterator p = childSequenceVector.begin();
1038 p != childSequenceVector.end(); p++) {
1039 if (!(*p)->getAsTyped()->getAsConstantUnion())
1040 return false;
1041 }
1042 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001043
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001044 return allConstant;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001045}
1046
1047// This function is used to test for the correctness of the parameters passed to various constructor functions
1048// and also convert them to the right datatype if it is allowed and required.
1049//
1050// Returns 0 for an error or the constructed node (aggregate or typed) for no error.
1051//
1052TIntermTyped* TParseContext::addConstructor(TIntermNode* node, const TType* type, TOperator op, TFunction* fnCall, TSourceLoc line)
1053{
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001054 if (node == 0)
1055 return 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001056
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001057 TIntermAggregate* aggrNode = node->getAsAggregate();
1058
alokp@chromium.org58e54292010-08-24 21:40:03 +00001059 TTypeList::const_iterator memberTypes;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001060 if (op == EOpConstructStruct)
1061 memberTypes = type->getStruct()->begin();
1062
1063 TType elementType = *type;
1064 if (type->isArray())
1065 elementType.clearArrayness();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001066
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001067 bool singleArg;
1068 if (aggrNode) {
1069 if (aggrNode->getOp() != EOpNull || aggrNode->getSequence().size() == 1)
1070 singleArg = true;
1071 else
1072 singleArg = false;
1073 } else
1074 singleArg = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001075
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001076 TIntermTyped *newNode;
1077 if (singleArg) {
1078 // If structure constructor or array constructor is being called
1079 // for only one parameter inside the structure, we need to call constructStruct function once.
1080 if (type->isArray())
1081 newNode = constructStruct(node, &elementType, 1, node->getLine(), false);
1082 else if (op == EOpConstructStruct)
1083 newNode = constructStruct(node, (*memberTypes).type, 1, node->getLine(), false);
1084 else
1085 newNode = constructBuiltIn(type, op, node, node->getLine(), false);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001086
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001087 if (newNode && newNode->getAsAggregate()) {
1088 TIntermTyped* constConstructor = foldConstConstructor(newNode->getAsAggregate(), *type);
1089 if (constConstructor)
1090 return constConstructor;
1091 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001092
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001093 return newNode;
1094 }
1095
1096 //
1097 // Handle list of arguments.
1098 //
1099 TIntermSequence &sequenceVector = aggrNode->getSequence() ; // Stores the information about the parameter to the constructor
1100 // if the structure constructor contains more than one parameter, then construct
1101 // each parameter
1102
1103 int paramCount = 0; // keeps a track of the constructor parameter number being checked
1104
1105 // for each parameter to the constructor call, check to see if the right type is passed or convert them
1106 // to the right type if possible (and allowed).
1107 // for structure constructors, just check if the right type is passed, no conversion is allowed.
1108
1109 for (TIntermSequence::iterator p = sequenceVector.begin();
1110 p != sequenceVector.end(); p++, paramCount++) {
1111 if (type->isArray())
1112 newNode = constructStruct(*p, &elementType, paramCount+1, node->getLine(), true);
1113 else if (op == EOpConstructStruct)
1114 newNode = constructStruct(*p, (memberTypes[paramCount]).type, paramCount+1, node->getLine(), true);
1115 else
1116 newNode = constructBuiltIn(type, op, *p, node->getLine(), true);
1117
1118 if (newNode) {
1119 *p = newNode;
1120 }
1121 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001122
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001123 TIntermTyped* constructor = intermediate.setAggregateOperator(aggrNode, op, line);
1124 TIntermTyped* constConstructor = foldConstConstructor(constructor->getAsAggregate(), *type);
1125 if (constConstructor)
1126 return constConstructor;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001127
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001128 return constructor;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001129}
1130
1131TIntermTyped* TParseContext::foldConstConstructor(TIntermAggregate* aggrNode, const TType& type)
1132{
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001133 bool canBeFolded = areAllChildConst(aggrNode);
1134 aggrNode->setType(type);
1135 if (canBeFolded) {
1136 bool returnVal = false;
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001137 ConstantUnion* unionArray = new ConstantUnion[type.getObjectSize()];
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001138 if (aggrNode->getSequence().size() == 1) {
1139 returnVal = intermediate.parseConstTree(aggrNode->getLine(), aggrNode, unionArray, aggrNode->getOp(), symbolTable, type, true);
1140 }
1141 else {
1142 returnVal = intermediate.parseConstTree(aggrNode->getLine(), aggrNode, unionArray, aggrNode->getOp(), symbolTable, type);
1143 }
1144 if (returnVal)
1145 return 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001146
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001147 return intermediate.addConstantUnion(unionArray, type, aggrNode->getLine());
1148 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001149
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001150 return 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001151}
1152
1153// Function for constructor implementation. Calls addUnaryMath with appropriate EOp value
1154// for the parameter to the constructor (passed to this function). Essentially, it converts
1155// the parameter types correctly. If a constructor expects an int (like ivec2) and is passed a
1156// float, then float is converted to int.
1157//
1158// Returns 0 for an error or the constructed node.
1159//
1160TIntermTyped* TParseContext::constructBuiltIn(const TType* type, TOperator op, TIntermNode* node, TSourceLoc line, bool subset)
1161{
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001162 TIntermTyped* newNode;
1163 TOperator basicOp;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001164
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001165 //
1166 // First, convert types as needed.
1167 //
1168 switch (op) {
1169 case EOpConstructVec2:
1170 case EOpConstructVec3:
1171 case EOpConstructVec4:
1172 case EOpConstructMat2:
1173 case EOpConstructMat3:
1174 case EOpConstructMat4:
1175 case EOpConstructFloat:
1176 basicOp = EOpConstructFloat;
1177 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001178
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001179 case EOpConstructIVec2:
1180 case EOpConstructIVec3:
1181 case EOpConstructIVec4:
1182 case EOpConstructInt:
1183 basicOp = EOpConstructInt;
1184 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001185
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001186 case EOpConstructBVec2:
1187 case EOpConstructBVec3:
1188 case EOpConstructBVec4:
1189 case EOpConstructBool:
1190 basicOp = EOpConstructBool;
1191 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001192
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001193 default:
1194 error(line, "unsupported construction", "", "");
1195 recover();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001196
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001197 return 0;
1198 }
1199 newNode = intermediate.addUnaryMath(basicOp, node, node->getLine(), symbolTable);
1200 if (newNode == 0) {
1201 error(line, "can't convert", "constructor", "");
1202 return 0;
1203 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001204
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001205 //
1206 // Now, if there still isn't an operation to do the construction, and we need one, add one.
1207 //
1208
1209 // Otherwise, skip out early.
1210 if (subset || (newNode != node && newNode->getType() == *type))
1211 return newNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001212
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001213 // setAggregateOperator will insert a new node for the constructor, as needed.
1214 return intermediate.setAggregateOperator(newNode, op, line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001215}
1216
1217// This function tests for the type of the parameters to the structures constructors. Raises
1218// an error message if the expected type does not match the parameter passed to the constructor.
1219//
1220// Returns 0 for an error or the input node itself if the expected and the given parameter types match.
1221//
1222TIntermTyped* TParseContext::constructStruct(TIntermNode* node, TType* type, int paramCount, TSourceLoc line, bool subset)
1223{
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001224 if (*type == node->getAsTyped()->getType()) {
1225 if (subset)
1226 return node->getAsTyped();
1227 else
1228 return intermediate.setAggregateOperator(node->getAsTyped(), EOpConstructStruct, line);
1229 } else {
1230 error(line, "", "constructor", "cannot convert parameter %d from '%s' to '%s'", paramCount,
1231 node->getAsTyped()->getType().getBasicString(), type->getBasicString());
1232 recover();
1233 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001234
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001235 return 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001236}
1237
1238//
1239// This function returns the tree representation for the vector field(s) being accessed from contant vector.
1240// If only one component of vector is accessed (v.x or v[0] where v is a contant vector), then a contant node is
1241// returned, else an aggregate node is returned (for v.xy). The input to this function could either be the symbol
1242// node or it could be the intermediate tree representation of accessing fields in a constant structure or column of
1243// a constant matrix.
1244//
1245TIntermTyped* TParseContext::addConstVectorNode(TVectorFields& fields, TIntermTyped* node, TSourceLoc line)
1246{
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001247 TIntermTyped* typedNode;
1248 TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001249
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001250 ConstantUnion *unionArray;
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001251 if (tempConstantNode) {
1252 unionArray = tempConstantNode->getUnionArrayPointer();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001253
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001254 if (!unionArray) { // this error message should never be raised
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001255 infoSink.info.message(EPrefixInternalError, "ConstantUnion not initialized in addConstVectorNode function", line);
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001256 recover();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001257
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001258 return node;
1259 }
1260 } else { // The node has to be either a symbol node or an aggregate node or a tempConstant node, else, its an error
1261 error(line, "Cannot offset into the vector", "Error", "");
1262 recover();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001263
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001264 return 0;
1265 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001266
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001267 ConstantUnion* constArray = new ConstantUnion[fields.num];
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001268
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001269 for (int i = 0; i < fields.num; i++) {
1270 if (fields.offsets[i] >= node->getType().getObjectSize()) {
1271 error(line, "", "[", "vector field selection out of range '%d'", fields.offsets[i]);
1272 recover();
1273 fields.offsets[i] = 0;
1274 }
1275
1276 constArray[i] = unionArray[fields.offsets[i]];
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001277
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001278 }
1279 typedNode = intermediate.addConstantUnion(constArray, node->getType(), line);
1280 return typedNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001281}
1282
1283//
1284// This function returns the column being accessed from a constant matrix. The values are retrieved from
1285// the symbol table and parse-tree is built for a vector (each column of a matrix is a vector). The input
1286// to the function could either be a symbol node (m[0] where m is a constant matrix)that represents a
1287// constant matrix or it could be the tree representation of the constant matrix (s.m1[0] where s is a constant structure)
1288//
1289TIntermTyped* TParseContext::addConstMatrixNode(int index, TIntermTyped* node, TSourceLoc line)
1290{
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001291 TIntermTyped* typedNode;
1292 TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001293
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001294 if (index >= node->getType().getNominalSize()) {
1295 error(line, "", "[", "matrix field selection out of range '%d'", index);
1296 recover();
1297 index = 0;
1298 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001299
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001300 if (tempConstantNode) {
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001301 ConstantUnion* unionArray = tempConstantNode->getUnionArrayPointer();
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001302 int size = tempConstantNode->getType().getNominalSize();
1303 typedNode = intermediate.addConstantUnion(&unionArray[size*index], tempConstantNode->getType(), line);
1304 } else {
1305 error(line, "Cannot offset into the matrix", "Error", "");
1306 recover();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001307
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001308 return 0;
1309 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001310
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001311 return typedNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001312}
1313
1314
1315//
1316// This function returns an element of an array accessed from a constant array. The values are retrieved from
1317// the symbol table and parse-tree is built for the type of the element. The input
1318// to the function could either be a symbol node (a[0] where a is a constant array)that represents a
1319// constant array or it could be the tree representation of the constant array (s.a1[0] where s is a constant structure)
1320//
1321TIntermTyped* TParseContext::addConstArrayNode(int index, TIntermTyped* node, TSourceLoc line)
1322{
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001323 TIntermTyped* typedNode;
1324 TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion();
1325 TType arrayElementType = node->getType();
1326 arrayElementType.clearArrayness();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001327
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001328 if (index >= node->getType().getArraySize()) {
1329 error(line, "", "[", "array field selection out of range '%d'", index);
1330 recover();
1331 index = 0;
1332 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001333
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001334 int arrayElementSize = arrayElementType.getObjectSize();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001335
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001336 if (tempConstantNode) {
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001337 ConstantUnion* unionArray = tempConstantNode->getUnionArrayPointer();
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001338 typedNode = intermediate.addConstantUnion(&unionArray[arrayElementSize * index], tempConstantNode->getType(), line);
1339 } else {
1340 error(line, "Cannot offset into the array", "Error", "");
1341 recover();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001342
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001343 return 0;
1344 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001345
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001346 return typedNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001347}
1348
1349
1350//
1351// This function returns the value of a particular field inside a constant structure from the symbol table.
1352// If there is an embedded/nested struct, it appropriately calls addConstStructNested or addConstStructFromAggr
1353// function and returns the parse-tree with the values of the embedded/nested struct.
1354//
1355TIntermTyped* TParseContext::addConstStruct(TString& identifier, TIntermTyped* node, TSourceLoc line)
1356{
alokp@chromium.org58e54292010-08-24 21:40:03 +00001357 const TTypeList* fields = node->getType().getStruct();
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001358 TIntermTyped *typedNode;
1359 int instanceSize = 0;
1360 unsigned int index = 0;
1361 TIntermConstantUnion *tempConstantNode = node->getAsConstantUnion();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001362
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001363 for ( index = 0; index < fields->size(); ++index) {
1364 if ((*fields)[index].type->getFieldName() == identifier) {
1365 break;
1366 } else {
1367 instanceSize += (*fields)[index].type->getObjectSize();
1368 }
1369 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001370
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001371 if (tempConstantNode) {
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001372 ConstantUnion* constArray = tempConstantNode->getUnionArrayPointer();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001373
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001374 typedNode = intermediate.addConstantUnion(constArray+instanceSize, tempConstantNode->getType(), line); // type will be changed in the calling function
1375 } else {
1376 error(line, "Cannot offset into the structure", "Error", "");
1377 recover();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001378
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001379 return 0;
1380 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001381
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001382 return typedNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001383}
1384
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001385OS_TLSIndex GlobalParseContextIndex = OS_INVALID_TLS_INDEX;
1386
1387bool InitializeParseContextIndex()
1388{
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001389 if (GlobalParseContextIndex != OS_INVALID_TLS_INDEX) {
1390 assert(0 && "InitializeParseContextIndex(): Parse Context already initalised");
1391 return false;
1392 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001393
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001394 //
1395 // Allocate a TLS index.
1396 //
1397 GlobalParseContextIndex = OS_AllocTLSIndex();
1398
1399 if (GlobalParseContextIndex == OS_INVALID_TLS_INDEX) {
1400 assert(0 && "InitializeParseContextIndex(): Parse Context already initalised");
1401 return false;
1402 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001403
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001404 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001405}
1406
alokp@chromium.org34b99cd2010-07-27 18:37:55 +00001407bool FreeParseContextIndex()
1408{
1409 OS_TLSIndex tlsiIndex = GlobalParseContextIndex;
1410
1411 if (GlobalParseContextIndex == OS_INVALID_TLS_INDEX) {
1412 assert(0 && "FreeParseContextIndex(): Parse Context index not initalised");
1413 return false;
1414 }
1415
1416 GlobalParseContextIndex = OS_INVALID_TLS_INDEX;
1417
1418 return OS_FreeTLSIndex(tlsiIndex);
1419}
1420
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001421bool InitializeGlobalParseContext()
1422{
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001423 if (GlobalParseContextIndex == OS_INVALID_TLS_INDEX) {
1424 assert(0 && "InitializeGlobalParseContext(): Parse Context index not initalised");
1425 return false;
1426 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001427
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001428 TThreadParseContext *lpParseContext = static_cast<TThreadParseContext *>(OS_GetTLSValue(GlobalParseContextIndex));
1429 if (lpParseContext != 0) {
1430 assert(0 && "InitializeParseContextIndex(): Parse Context already initalised");
1431 return false;
1432 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001433
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001434 TThreadParseContext *lpThreadData = new TThreadParseContext();
1435 if (lpThreadData == 0) {
1436 assert(0 && "InitializeGlobalParseContext(): Unable to create thread parse context");
1437 return false;
1438 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001439
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001440 lpThreadData->lpGlobalParseContext = 0;
1441 OS_SetTLSValue(GlobalParseContextIndex, lpThreadData);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001442
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001443 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001444}
1445
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001446bool FreeParseContext()
1447{
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001448 if (GlobalParseContextIndex == OS_INVALID_TLS_INDEX) {
1449 assert(0 && "FreeParseContext(): Parse Context index not initalised");
1450 return false;
1451 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001452
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001453 TThreadParseContext *lpParseContext = static_cast<TThreadParseContext *>(OS_GetTLSValue(GlobalParseContextIndex));
1454 if (lpParseContext)
1455 delete lpParseContext;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001456
daniel@transgaming.comea15b0e2010-04-29 03:32:36 +00001457 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001458}
1459
alokp@chromium.org34b99cd2010-07-27 18:37:55 +00001460TParseContextPointer& GetGlobalParseContext()
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001461{
alokp@chromium.org34b99cd2010-07-27 18:37:55 +00001462 //
1463 // Minimal error checking for speed
1464 //
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001465
alokp@chromium.org34b99cd2010-07-27 18:37:55 +00001466 TThreadParseContext *lpParseContext = static_cast<TThreadParseContext *>(OS_GetTLSValue(GlobalParseContextIndex));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001467
alokp@chromium.org34b99cd2010-07-27 18:37:55 +00001468 return lpParseContext->lpGlobalParseContext;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001469}
alokp@chromium.org34b99cd2010-07-27 18:37:55 +00001470