1 // 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 7 #include "compiler/ParseHelper.h" 8 9 // 10 // Use this class to carry along data from node to node in 11 // the traversal 12 // 13 class TConstTraverser : public TIntermTraverser { 14 public: 15 TConstTraverser(ConstantUnion* cUnion, bool singleConstParam, TOperator constructType, TInfoSink& sink, TSymbolTable& symTable, TType& t) 16 : error(false), 17 index(0), 18 unionArray(cUnion), 19 type(t), 20 constructorType(constructType), 21 singleConstantParam(singleConstParam), 22 infoSink(sink), 23 symbolTable(symTable), 24 size(0), 25 isMatrix(false), 26 matrixSize(0) { 27 } 28 29 bool error; 30 31 protected: 32 void visitSymbol(TIntermSymbol*); 33 void visitConstantUnion(TIntermConstantUnion*); 34 bool visitBinary(Visit visit, TIntermBinary*); 35 bool visitUnary(Visit visit, TIntermUnary*); 36 bool visitSelection(Visit visit, TIntermSelection*); 37 bool visitAggregate(Visit visit, TIntermAggregate*); 38 bool visitLoop(Visit visit, TIntermLoop*); 39 bool visitBranch(Visit visit, TIntermBranch*); 40 41 int index; 42 ConstantUnion *unionArray; 43 TType type; 44 TOperator constructorType; 45 bool singleConstantParam; 46 TInfoSink& infoSink; 47 TSymbolTable& symbolTable; 48 int size; // size of the constructor ( 4 for vec4) 49 bool isMatrix; 50 int matrixSize; // dimension of the matrix (nominal size and not the instance size) 51 }; 52 53 // 54 // The rest of the file are the traversal functions. The last one 55 // is the one that starts the traversal. 56 // 57 // Return true from interior nodes to have the external traversal 58 // continue on to children. If you process children yourself, 59 // return false. 60 // 61 62 void TConstTraverser::visitSymbol(TIntermSymbol* node) 63 { 64 infoSink.info.message(EPrefixInternalError, "Symbol Node found in constant constructor", node->getLine()); 65 return; 66 67 } 68 69 bool TConstTraverser::visitBinary(Visit visit, TIntermBinary* node) 70 { 71 TQualifier qualifier = node->getType().getQualifier(); 72 73 if (qualifier != EvqConst) { 74 TString buf; 75 buf.append("'constructor' : assigning non-constant to "); 76 buf.append(type.getCompleteString()); 77 infoSink.info.message(EPrefixError, buf.c_str(), node->getLine()); 78 error = true; 79 return false; 80 } 81 82 infoSink.info.message(EPrefixInternalError, "Binary Node found in constant constructor", node->getLine()); 83 84 return false; 85 } 86 87 bool TConstTraverser::visitUnary(Visit visit, TIntermUnary* node) 88 { 89 TString buf; 90 buf.append("'constructor' : assigning non-constant to "); 91 buf.append(type.getCompleteString()); 92 infoSink.info.message(EPrefixError, buf.c_str(), node->getLine()); 93 error = true; 94 return false; 95 } 96 97 bool TConstTraverser::visitAggregate(Visit visit, TIntermAggregate* node) 98 { 99 if (!node->isConstructor() && node->getOp() != EOpComma) { 100 TString buf; 101 buf.append("'constructor' : assigning non-constant to "); 102 buf.append(type.getCompleteString()); 103 infoSink.info.message(EPrefixError, buf.c_str(), node->getLine()); 104 error = true; 105 return false; 106 } 107 108 if (node->getSequence().size() == 0) { 109 error = true; 110 return false; 111 } 112 113 bool flag = node->getSequence().size() == 1 && node->getSequence()[0]->getAsTyped()->getAsConstantUnion(); 114 if (flag) 115 { 116 singleConstantParam = true; 117 constructorType = node->getOp(); 118 size = node->getType().getObjectSize(); 119 120 if (node->getType().isMatrix()) { 121 isMatrix = true; 122 matrixSize = node->getType().getNominalSize(); 123 } 124 } 125 126 for (TIntermSequence::iterator p = node->getSequence().begin(); 127 p != node->getSequence().end(); p++) { 128 129 if (node->getOp() == EOpComma) 130 index = 0; 131 132 (*p)->traverse(this); 133 } 134 if (flag) 135 { 136 singleConstantParam = false; 137 constructorType = EOpNull; 138 size = 0; 139 isMatrix = false; 140 matrixSize = 0; 141 } 142 return false; 143 } 144 145 bool TConstTraverser::visitSelection(Visit visit, TIntermSelection* node) 146 { 147 infoSink.info.message(EPrefixInternalError, "Selection Node found in constant constructor", node->getLine()); 148 error = true; 149 return false; 150 } 151 152 void TConstTraverser::visitConstantUnion(TIntermConstantUnion* node) 153 { 154 ConstantUnion* leftUnionArray = unionArray; 155 int instanceSize = type.getObjectSize(); 156 157 if (index >= instanceSize) 158 return; 159 160 if (!singleConstantParam) { 161 int size = node->getType().getObjectSize(); 162 163 ConstantUnion *rightUnionArray = node->getUnionArrayPointer(); 164 for (int i=0; i < size; i++) { 165 if (index >= instanceSize) 166 return; 167 leftUnionArray[index] = rightUnionArray[i]; 168 169 (index)++; 170 } 171 } else { 172 int totalSize = index + size; 173 ConstantUnion *rightUnionArray = node->getUnionArrayPointer(); 174 if (!isMatrix) { 175 int count = 0; 176 for (int i = index; i < totalSize; i++) { 177 if (i >= instanceSize) 178 return; 179 180 leftUnionArray[i] = rightUnionArray[count]; 181 182 (index)++; 183 184 if (node->getType().getObjectSize() > 1) 185 count++; 186 } 187 } else { // for matrix constructors 188 int count = 0; 189 int element = index; 190 for (int i = index; i < totalSize; i++) { 191 if (i >= instanceSize) 192 return; 193 if (element - i == 0 || (i - element) % (matrixSize + 1) == 0 ) 194 leftUnionArray[i] = rightUnionArray[count]; 195 else 196 leftUnionArray[i].setFConst(0.0f); 197 198 (index)++; 199 200 if (node->getType().getObjectSize() > 1) 201 count++; 202 } 203 } 204 } 205 } 206 207 bool TConstTraverser::visitLoop(Visit visit, TIntermLoop* node) 208 { 209 infoSink.info.message(EPrefixInternalError, "Loop Node found in constant constructor", node->getLine()); 210 error = true; 211 return false; 212 } 213 214 bool TConstTraverser::visitBranch(Visit visit, TIntermBranch* node) 215 { 216 infoSink.info.message(EPrefixInternalError, "Branch Node found in constant constructor", node->getLine()); 217 error = true; 218 return false; 219 } 220 221 // 222 // This function is the one to call externally to start the traversal. 223 // Individual functions can be initialized to 0 to skip processing of that 224 // type of node. It's children will still be processed. 225 // 226 bool TIntermediate::parseConstTree(TSourceLoc line, TIntermNode* root, ConstantUnion* unionArray, TOperator constructorType, TSymbolTable& symbolTable, TType t, bool singleConstantParam) 227 { 228 if (root == 0) 229 return false; 230 231 TConstTraverser it(unionArray, singleConstantParam, constructorType, infoSink, symbolTable, t); 232 233 root->traverse(&it); 234 if (it.error) 235 return true; 236 else 237 return false; 238 } 239