TIntermTyped *TIntermediate::addComma(TIntermTyped *left, TIntermTyped *right, const TSourceLoc &line, int shaderVersion) { TQualifier resultQualifier = EvqConst; // ESSL3.00 section 12.43: The result of a sequence operator is not a constant-expression. if (shaderVersion >= 300 || left->getQualifier() != EvqConst || right->getQualifier() != EvqConst) { resultQualifier = EvqTemporary; } TIntermTyped *commaNode = nullptr; if (!left->hasSideEffects()) { commaNode = right; } else { commaNode = growAggregate(left, right, line); commaNode->getAsAggregate()->setOp(EOpComma); commaNode->setType(right->getType()); } commaNode->getTypePointer()->setQualifier(resultQualifier); return commaNode; }
TIntermTyped* TIntermediate::addComma(TIntermTyped* left, TIntermTyped* right, TSourceLoc line) { if (left->getType().getQualifier() == EvqConst && right->getType().getQualifier() == EvqConst) { return right; } else { TIntermTyped *commaAggregate = growAggregate(left, right, line); commaAggregate->getAsAggregate()->setOp(EOpComma); commaAggregate->setType(right->getType()); commaAggregate->getTypePointer()->setQualifier(EvqTemporary); return commaAggregate; } }
TIntermTyped* ir_add_comma(TIntermTyped* left, TIntermTyped* right, TSourceLoc line) { if (left->getType().getQualifier() == EvqConst && right->getType().getQualifier() == EvqConst) { return right; } else { TIntermTyped *commaAggregate = ir_grow_aggregate(left, right, line); commaAggregate->getAsAggregate()->setOperator(EOpComma); commaAggregate->setType(right->getType()); commaAggregate->getTypePointer()->changeQualifier(EvqTemporary); return commaAggregate; } }
// // Both test and if necessary, spit out an error, to see if the node is really // an l-value that can be operated on this way. // // Returns true if the was an error. // bool TParseContext::lValueErrorCheck(int line, const char* op, TIntermTyped* node) { TIntermSymbol* symNode = node->getAsSymbolNode(); TIntermBinary* binaryNode = node->getAsBinaryNode(); if (binaryNode) { bool errorReturn; switch(binaryNode->getOp()) { case EOpIndexDirect: case EOpIndexIndirect: case EOpIndexDirectStruct: return lValueErrorCheck(line, op, binaryNode->getLeft()); case EOpVectorSwizzle: errorReturn = lValueErrorCheck(line, op, binaryNode->getLeft()); if (!errorReturn) { int offset[4] = {0,0,0,0}; TIntermTyped* rightNode = binaryNode->getRight(); TIntermAggregate *aggrNode = rightNode->getAsAggregate(); for (TIntermSequence::iterator p = aggrNode->getSequence().begin(); p != aggrNode->getSequence().end(); p++) { int value = (*p)->getAsTyped()->getAsConstantUnion()->getUnionArrayPointer()->getIConst(); offset[value]++; if (offset[value] > 1) { error(line, " l-value of swizzle cannot have duplicate components", op, "", ""); return true; } } } return errorReturn; default: break; } error(line, " l-value required", op, "", ""); return true; } const char* symbol = 0; if (symNode != 0) symbol = symNode->getSymbol().c_str(); const char* message = 0; switch (node->getQualifier()) { case EvqConst: message = "can't modify a const"; break; case EvqConstReadOnly: message = "can't modify a const"; break; case EvqAttribute: message = "can't modify an attribute"; break; case EvqUniform: message = "can't modify a uniform"; break; case EvqVaryingIn: message = "can't modify a varying"; break; case EvqInput: message = "can't modify an input"; break; case EvqFragCoord: message = "can't modify gl_FragCoord"; break; case EvqFrontFacing: message = "can't modify gl_FrontFacing"; break; case EvqPointCoord: message = "can't modify gl_PointCoord"; break; default: // // Type that can't be written to? // switch (node->getBasicType()) { case EbtSampler2D: case EbtSamplerCube: message = "can't modify a sampler"; break; case EbtVoid: message = "can't modify void"; break; default: break; } } if (message == 0 && binaryNode == 0 && symNode == 0) { error(line, " l-value required", op, "", ""); return true; } // // Everything else is okay, no error. // if (message == 0) return false; // // If we get here, we have an error and a message. // if (symNode) error(line, " l-value required", op, "\"%s\" (%s)", symbol, message); else error(line, " l-value required", op, "(%s)", message); return true; }
// This function is used to test for the correctness of the parameters passed to various constructor functions // and also convert them to the right datatype if it is allowed and required. // // Returns 0 for an error or the constructed node (aggregate or typed) for no error. // TIntermTyped* TParseContext::addConstructor(TIntermNode* node, const TType* type, TOperator op, TFunction* fnCall, TSourceLoc line) { if (node == 0) return 0; TIntermAggregate* aggrNode = node->getAsAggregate(); TTypeList::const_iterator memberTypes; if (op == EOpConstructStruct) memberTypes = type->getStruct()->begin(); TType elementType = *type; if (type->isArray()) elementType.clearArrayness(); bool singleArg; if (aggrNode) { if (aggrNode->getOp() != EOpNull || aggrNode->getSequence().size() == 1) singleArg = true; else singleArg = false; } else singleArg = true; TIntermTyped *newNode; if (singleArg) { // If structure constructor or array constructor is being called // for only one parameter inside the structure, we need to call constructStruct function once. if (type->isArray()) newNode = constructStruct(node, &elementType, 1, node->getLine(), false); else if (op == EOpConstructStruct) newNode = constructStruct(node, (*memberTypes).type, 1, node->getLine(), false); else newNode = constructBuiltIn(type, op, node, node->getLine(), false); if (newNode && newNode->getAsAggregate()) { TIntermTyped* constConstructor = foldConstConstructor(newNode->getAsAggregate(), *type); if (constConstructor) return constConstructor; } return newNode; } // // Handle list of arguments. // TIntermSequence &sequenceVector = aggrNode->getSequence() ; // Stores the information about the parameter to the constructor // if the structure constructor contains more than one parameter, then construct // each parameter int paramCount = 0; // keeps a track of the constructor parameter number being checked // for each parameter to the constructor call, check to see if the right type is passed or convert them // to the right type if possible (and allowed). // for structure constructors, just check if the right type is passed, no conversion is allowed. for (TIntermSequence::iterator p = sequenceVector.begin(); p != sequenceVector.end(); p++, paramCount++) { if (type->isArray()) newNode = constructStruct(*p, &elementType, paramCount+1, node->getLine(), true); else if (op == EOpConstructStruct) newNode = constructStruct(*p, (memberTypes[paramCount]).type, paramCount+1, node->getLine(), true); else newNode = constructBuiltIn(type, op, *p, node->getLine(), true); if (newNode) { *p = newNode; } } TIntermTyped* constructor = intermediate.setAggregateOperator(aggrNode, op, line); TIntermTyped* constConstructor = foldConstConstructor(constructor->getAsAggregate(), *type); if (constConstructor) return constConstructor; return constructor; }