1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/angle/src/compiler/parseConst.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,245 @@ 1.4 +// 1.5 +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. 1.6 +// Use of this source code is governed by a BSD-style license that can be 1.7 +// found in the LICENSE file. 1.8 +// 1.9 + 1.10 +#include "compiler/ParseHelper.h" 1.11 + 1.12 +// 1.13 +// Use this class to carry along data from node to node in 1.14 +// the traversal 1.15 +// 1.16 +class TConstTraverser : public TIntermTraverser { 1.17 +public: 1.18 + TConstTraverser(ConstantUnion* cUnion, bool singleConstParam, TOperator constructType, TInfoSink& sink, TSymbolTable& symTable, TType& t) 1.19 + : error(false), 1.20 + index(0), 1.21 + unionArray(cUnion), 1.22 + type(t), 1.23 + constructorType(constructType), 1.24 + singleConstantParam(singleConstParam), 1.25 + infoSink(sink), 1.26 + symbolTable(symTable), 1.27 + size(0), 1.28 + isMatrix(false), 1.29 + matrixSize(0) { 1.30 + } 1.31 + 1.32 + bool error; 1.33 + 1.34 +protected: 1.35 + void visitSymbol(TIntermSymbol*); 1.36 + void visitConstantUnion(TIntermConstantUnion*); 1.37 + bool visitBinary(Visit visit, TIntermBinary*); 1.38 + bool visitUnary(Visit visit, TIntermUnary*); 1.39 + bool visitSelection(Visit visit, TIntermSelection*); 1.40 + bool visitAggregate(Visit visit, TIntermAggregate*); 1.41 + bool visitLoop(Visit visit, TIntermLoop*); 1.42 + bool visitBranch(Visit visit, TIntermBranch*); 1.43 + 1.44 + size_t index; 1.45 + ConstantUnion *unionArray; 1.46 + TType type; 1.47 + TOperator constructorType; 1.48 + bool singleConstantParam; 1.49 + TInfoSink& infoSink; 1.50 + TSymbolTable& symbolTable; 1.51 + size_t size; // size of the constructor ( 4 for vec4) 1.52 + bool isMatrix; 1.53 + size_t matrixSize; // dimension of the matrix (nominal size and not the instance size) 1.54 +}; 1.55 + 1.56 +// 1.57 +// The rest of the file are the traversal functions. The last one 1.58 +// is the one that starts the traversal. 1.59 +// 1.60 +// Return true from interior nodes to have the external traversal 1.61 +// continue on to children. If you process children yourself, 1.62 +// return false. 1.63 +// 1.64 + 1.65 +void TConstTraverser::visitSymbol(TIntermSymbol* node) 1.66 +{ 1.67 + infoSink.info.message(EPrefixInternalError, node->getLine(), "Symbol Node found in constant constructor"); 1.68 + return; 1.69 + 1.70 +} 1.71 + 1.72 +bool TConstTraverser::visitBinary(Visit visit, TIntermBinary* node) 1.73 +{ 1.74 + TQualifier qualifier = node->getType().getQualifier(); 1.75 + 1.76 + if (qualifier != EvqConst) { 1.77 + TString buf; 1.78 + buf.append("'constructor' : assigning non-constant to "); 1.79 + buf.append(type.getCompleteString()); 1.80 + infoSink.info.message(EPrefixError, node->getLine(), buf.c_str()); 1.81 + error = true; 1.82 + return false; 1.83 + } 1.84 + 1.85 + infoSink.info.message(EPrefixInternalError, node->getLine(), "Binary Node found in constant constructor"); 1.86 + 1.87 + return false; 1.88 +} 1.89 + 1.90 +bool TConstTraverser::visitUnary(Visit visit, TIntermUnary* node) 1.91 +{ 1.92 + TString buf; 1.93 + buf.append("'constructor' : assigning non-constant to "); 1.94 + buf.append(type.getCompleteString()); 1.95 + infoSink.info.message(EPrefixError, node->getLine(), buf.c_str()); 1.96 + error = true; 1.97 + return false; 1.98 +} 1.99 + 1.100 +bool TConstTraverser::visitAggregate(Visit visit, TIntermAggregate* node) 1.101 +{ 1.102 + if (!node->isConstructor() && node->getOp() != EOpComma) { 1.103 + TString buf; 1.104 + buf.append("'constructor' : assigning non-constant to "); 1.105 + buf.append(type.getCompleteString()); 1.106 + infoSink.info.message(EPrefixError, node->getLine(), buf.c_str()); 1.107 + error = true; 1.108 + return false; 1.109 + } 1.110 + 1.111 + if (node->getSequence().size() == 0) { 1.112 + error = true; 1.113 + return false; 1.114 + } 1.115 + 1.116 + bool flag = node->getSequence().size() == 1 && node->getSequence()[0]->getAsTyped()->getAsConstantUnion(); 1.117 + if (flag) 1.118 + { 1.119 + singleConstantParam = true; 1.120 + constructorType = node->getOp(); 1.121 + size = node->getType().getObjectSize(); 1.122 + 1.123 + if (node->getType().isMatrix()) { 1.124 + isMatrix = true; 1.125 + matrixSize = node->getType().getNominalSize(); 1.126 + } 1.127 + } 1.128 + 1.129 + for (TIntermSequence::iterator p = node->getSequence().begin(); 1.130 + p != node->getSequence().end(); p++) { 1.131 + 1.132 + if (node->getOp() == EOpComma) 1.133 + index = 0; 1.134 + 1.135 + (*p)->traverse(this); 1.136 + } 1.137 + if (flag) 1.138 + { 1.139 + singleConstantParam = false; 1.140 + constructorType = EOpNull; 1.141 + size = 0; 1.142 + isMatrix = false; 1.143 + matrixSize = 0; 1.144 + } 1.145 + return false; 1.146 +} 1.147 + 1.148 +bool TConstTraverser::visitSelection(Visit visit, TIntermSelection* node) 1.149 +{ 1.150 + infoSink.info.message(EPrefixInternalError, node->getLine(), "Selection Node found in constant constructor"); 1.151 + error = true; 1.152 + return false; 1.153 +} 1.154 + 1.155 +void TConstTraverser::visitConstantUnion(TIntermConstantUnion* node) 1.156 +{ 1.157 + if (!node->getUnionArrayPointer()) 1.158 + { 1.159 + // The constant was not initialized, this should already have been logged 1.160 + assert(infoSink.info.size() != 0); 1.161 + return; 1.162 + } 1.163 + 1.164 + ConstantUnion* leftUnionArray = unionArray; 1.165 + size_t instanceSize = type.getObjectSize(); 1.166 + 1.167 + if (index >= instanceSize) 1.168 + return; 1.169 + 1.170 + if (!singleConstantParam) { 1.171 + size_t size = node->getType().getObjectSize(); 1.172 + 1.173 + ConstantUnion *rightUnionArray = node->getUnionArrayPointer(); 1.174 + for (size_t i = 0; i < size; i++) { 1.175 + if (index >= instanceSize) 1.176 + return; 1.177 + leftUnionArray[index] = rightUnionArray[i]; 1.178 + 1.179 + (index)++; 1.180 + } 1.181 + } else { 1.182 + size_t totalSize = index + size; 1.183 + ConstantUnion *rightUnionArray = node->getUnionArrayPointer(); 1.184 + if (!isMatrix) { 1.185 + size_t count = 0; 1.186 + for (size_t i = index; i < totalSize; i++) { 1.187 + if (i >= instanceSize) 1.188 + return; 1.189 + 1.190 + leftUnionArray[i] = rightUnionArray[count]; 1.191 + 1.192 + (index)++; 1.193 + 1.194 + if (node->getType().getObjectSize() > 1) 1.195 + count++; 1.196 + } 1.197 + } else { // for matrix constructors 1.198 + size_t count = 0; 1.199 + size_t element = index; 1.200 + for (size_t i = index; i < totalSize; i++) { 1.201 + if (i >= instanceSize) 1.202 + return; 1.203 + if (element - i == 0 || (i - element) % (matrixSize + 1) == 0 ) 1.204 + leftUnionArray[i] = rightUnionArray[count]; 1.205 + else 1.206 + leftUnionArray[i].setFConst(0.0f); 1.207 + 1.208 + (index)++; 1.209 + 1.210 + if (node->getType().getObjectSize() > 1) 1.211 + count++; 1.212 + } 1.213 + } 1.214 + } 1.215 +} 1.216 + 1.217 +bool TConstTraverser::visitLoop(Visit visit, TIntermLoop* node) 1.218 +{ 1.219 + infoSink.info.message(EPrefixInternalError, node->getLine(), "Loop Node found in constant constructor"); 1.220 + error = true; 1.221 + return false; 1.222 +} 1.223 + 1.224 +bool TConstTraverser::visitBranch(Visit visit, TIntermBranch* node) 1.225 +{ 1.226 + infoSink.info.message(EPrefixInternalError, node->getLine(), "Branch Node found in constant constructor"); 1.227 + error = true; 1.228 + return false; 1.229 +} 1.230 + 1.231 +// 1.232 +// This function is the one to call externally to start the traversal. 1.233 +// Individual functions can be initialized to 0 to skip processing of that 1.234 +// type of node. It's children will still be processed. 1.235 +// 1.236 +bool TIntermediate::parseConstTree(const TSourceLoc& line, TIntermNode* root, ConstantUnion* unionArray, TOperator constructorType, TSymbolTable& symbolTable, TType t, bool singleConstantParam) 1.237 +{ 1.238 + if (root == 0) 1.239 + return false; 1.240 + 1.241 + TConstTraverser it(unionArray, singleConstantParam, constructorType, infoSink, symbolTable, t); 1.242 + 1.243 + root->traverse(&it); 1.244 + if (it.error) 1.245 + return true; 1.246 + else 1.247 + return false; 1.248 +}