else
return 0;
}
-
+
//
// Need a new node holding things together. Make
// one and promote it to the right type.
return 0;
node->updatePrecision();
-
+
//
// If they are both constants, they must be folded.
// (Unless it's the sequence (comma) operator, but that's handled in addComma().)
//
TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermTyped* child, TSourceLoc loc)
{
- if (child->getType().getBasicType() == EbtBlock)
+ if (child == 0)
return 0;
- if (child == 0)
+ if (child->getType().getBasicType() == EbtBlock)
return 0;
switch (op) {
loc = child->getLoc();
node->setLoc(loc);
node->setOperand(child);
-
+
if (! node->promote())
return 0;
// Treat it like a unary operator.
// addUnaryMath() should get the type correct on its own;
// including constness (which would differ from the prototype).
- //
+ //
TIntermTyped* child = childNode->getAsTyped();
if (child == 0)
return 0;
} else {
// setAggregateOperater() calls fold() for constant folding
TIntermTyped* node = setAggregateOperator(childNode, op, returnType, loc);
-
+
// if not folded, we'll still have an aggregate node to propagate precision with
if (node->getAsAggregate()) {
TPrecisionQualifier correctPrecision = returnType.getQualifier().precision;
for (unsigned int arg = 0; arg < sequence.size(); ++arg)
correctPrecision = std::max(correctPrecision, sequence[arg]->getAsTyped()->getQualifier().precision);
}
-
+
// Propagate precision through this node and its children. That algorithm stops
// when a precision is found, so start by clearing this subroot precision
node->getQualifier().precision = EpqNone;
//
// Convert the node's type to the given type, as allowed by the operation involved: 'op'.
-// For implicit conversions, 'op' is not the requested conversion, it is the explicit
+// For implicit conversions, 'op' is not the requested conversion, it is the explicit
// operation requiring the implicit conversion.
//
// Returns a node representing the conversion, which could be the same
if (type.isArray() || node->getType().isArray())
return 0;
- // Note: callers are responsible for other aspects of shape,
+ // Note: callers are responsible for other aspects of shape,
// like vector and matrix sizes.
TBasicType promoteTo;
-
+
switch (op) {
//
// Explicit conversions (unary operations)
//
// List all the binary ops that can implicitly convert one operand to the other's type;
// This implements the 'policy' for implicit type conversion.
- //
+ //
case EOpLessThan:
case EOpGreaterThan:
case EOpLessThanEqual:
case EOpRightShift:
case EOpLeftShiftAssign:
case EOpRightShiftAssign:
- if ((type.getBasicType() == EbtInt ||
+ if ((type.getBasicType() == EbtInt ||
type.getBasicType() == EbtUint) &&
- (node->getType().getBasicType() == EbtInt ||
+ (node->getType().getBasicType() == EbtInt ||
node->getType().getBasicType() == EbtUint))
return node;
else
return 0;
}
-
+
if (node->getAsConstantUnion())
return promoteConstantUnion(promoteTo, node->getAsConstantUnion());
return 0;
}
break;
- default:
+ default:
return 0;
}
}
//
-// See if the 'from' type is allowed to be implicitly converted to the
+// See if the 'from' type is allowed to be implicitly converted to the
// 'to' type. This is not about vector/array/struct, only about basic type.
//
bool TIntermediate::canImplicitlyPromote(TBasicType from, TBasicType to) const
}
//
-// Safe way to combine two nodes into an aggregate. Works with null pointers,
+// Safe way to combine two nodes into an aggregate. Works with null pointers,
// a node that's not a aggregate yet, etc.
//
-// Returns the resulting aggregate, unless 0 was passed in for
+// Returns the resulting aggregate, unless 0 was passed in for
// both existing nodes.
//
TIntermAggregate* TIntermediate::growAggregate(TIntermNode* left, TIntermNode* right)
TIntermTyped* TIntermediate::addComma(TIntermTyped* left, TIntermTyped* right, const TSourceLoc& loc)
{
- // However, the lowest precedence operators of the sequence operator ( , ) and the assignment operators
+ // However, the lowest precedence operators of the sequence operator ( , ) and the assignment operators
// ... are not included in the operators that can create a constant expression.
//
- //if (left->getType().getQualifier().storage == EvqConst &&
+ //if (left->getType().getQualifier().storage == EvqConst &&
// right->getType().getQualifier().storage == EvqConst) {
// return right;
else
return 0;
}
-
+
// After conversion, types have to match.
if (falseBlock->getType() != trueBlock->getType())
return 0;
TIntermTyped* TIntermediate::addSwizzle(TVectorFields& fields, const TSourceLoc& loc)
{
-
+
TIntermAggregate* node = new TIntermAggregate(EOpSequence);
node->setLoc(loc);
// Return the base of the l-value (where following indexing quits working).
// Return nullptr if a chain following dereferences cannot be followed.
//
-// 'swizzleOkay' says whether or not it is okay to consider a swizzle
+// 'swizzleOkay' says whether or not it is okay to consider a swizzle
// a valid part of the dereference chain.
//
const TIntermTyped* TIntermediate::findLValueBase(const TIntermTyped* node, bool swizzleOkay)
if (! swizzleOkay) {
if (op == EOpVectorSwizzle)
return nullptr;
- if ((op == EOpIndexDirect || op == EOpIndexIndirect) &&
- (binary->getLeft()->getType().isVector() || binary->getLeft()->getType().isScalar()) &&
+ if ((op == EOpIndexDirect || op == EOpIndexIndirect) &&
+ (binary->getLeft()->getType().isVector() || binary->getLeft()->getType().isScalar()) &&
! binary->getLeft()->getType().isArray())
return nullptr;
}
// compilation unit by a linker, yet might not have been referenced
// by the AST.
//
- // Almost entirely, translation of symbols is driven by what's present
+ // Almost entirely, translation of symbols is driven by what's present
// in the AST traversal, not by translating the symbol table.
//
// However, there are some special cases:
// - From the specification: "Special built-in inputs gl_VertexID and
// gl_InstanceID are also considered active vertex attributes."
- // - Linker-based type mismatch error reporting needs to see all
+ // - Linker-based type mismatch error reporting needs to see all
// uniforms/ins/outs variables and blocks.
// - ftransform() can make gl_Vertex and gl_ModelViewProjectionMatrix active.
//
//}
if (language == EShLangVertex) {
- // the names won't be found in the symbol table unless the versions are right,
+ // the names won't be found in the symbol table unless the versions are right,
// so version logic does not need to be repeated here
addSymbolLinkageNode(linkage, symbolTable, "gl_VertexID");
addSymbolLinkageNode(linkage, symbolTable, "gl_InstanceID");
}
- // Add a child to the root node for the linker objects
+ // Add a child to the root node for the linker objects
linkage->setOperator(EOpLinkerObjects);
treeRoot = growAggregate(treeRoot, linkage);
}
//
bool TIntermOperator::modifiesState() const
{
- switch (op) {
- case EOpPostIncrement:
- case EOpPostDecrement:
- case EOpPreIncrement:
- case EOpPreDecrement:
- case EOpAssign:
- case EOpAddAssign:
- case EOpSubAssign:
- case EOpMulAssign:
+ switch (op) {
+ case EOpPostIncrement:
+ case EOpPostDecrement:
+ case EOpPreIncrement:
+ case EOpPreDecrement:
+ case EOpAssign:
+ case EOpAddAssign:
+ case EOpSubAssign:
+ case EOpMulAssign:
case EOpVectorTimesMatrixAssign:
case EOpVectorTimesScalarAssign:
case EOpMatrixTimesScalarAssign:
case EOpMatrixTimesMatrixAssign:
- case EOpDivAssign:
- case EOpModAssign:
- case EOpAndAssign:
- case EOpInclusiveOrAssign:
- case EOpExclusiveOrAssign:
- case EOpLeftShiftAssign:
- case EOpRightShiftAssign:
+ case EOpDivAssign:
+ case EOpModAssign:
+ case EOpAndAssign:
+ case EOpInclusiveOrAssign:
+ case EOpExclusiveOrAssign:
+ case EOpLeftShiftAssign:
+ case EOpRightShiftAssign:
return true;
default:
return false;
}
//
-// Make sure the type of a unary operator is appropriate for its
+// Make sure the type of a unary operator is appropriate for its
// combination of operation and operand type.
//
// Returns false in nothing makes sense.
case EOpPostDecrement:
case EOpPreIncrement:
case EOpPreDecrement:
- if (operand->getBasicType() != EbtInt &&
- operand->getBasicType() != EbtUint &&
+ if (operand->getBasicType() != EbtInt &&
+ operand->getBasicType() != EbtUint &&
operand->getBasicType() != EbtFloat &&
operand->getBasicType() != EbtDouble)
bool TIntermBinary::promote()
{
// Arrays and structures have to be exact matches.
- if ((left->isArray() || right->isArray() || left->getBasicType() == EbtStruct || right->getBasicType() == EbtStruct)
+ if ((left->isArray() || right->isArray() || left->getBasicType() == EbtStruct || right->getBasicType() == EbtStruct)
&& left->getType() != right->getType())
return false;
default:
break;
}
-
+
// Compare left and right, and finish with the cases where the operand types must match
switch (op) {
case EOpLessThan:
case EOpLogicalAnd:
case EOpLogicalOr:
- case EOpLogicalXor:
+ case EOpLogicalXor:
return left->getType() == right->getType();
// no shifts: they can mix types (scalar int can shift a vector uint, etc.)
} else {
return false;
}
- break;
+ break;
case EOpRightShift:
case EOpLeftShift:
if (right->isVector() || right->isMatrix())
setType(TType(basicType, EvqTemporary, right->getVectorSize(), right->getMatrixCols(), right->getMatrixRows()));
break;
-
+
default:
return false;
}
if (getType() != left->getType())
return false;
break;
- default:
+ default:
break;
}
-
+
return true;
}
case EbtDouble:
leftUnionArray[i].setDConst(static_cast<double>(rightUnionArray[i].getDConst()));
break;
- default:
+ default:
return node;
- }
+ }
break;
case EbtDouble:
switch (node->getType().getBasicType()) {
case EbtDouble:
leftUnionArray[i] = rightUnionArray[i];
break;
- default:
+ default:
return node;
- }
+ }
break;
case EbtInt:
switch (node->getType().getBasicType()) {
case EbtDouble:
leftUnionArray[i].setIConst(static_cast<int>(rightUnionArray[i].getDConst()));
break;
- default:
+ default:
return node;
- }
+ }
break;
case EbtUint:
switch (node->getType().getBasicType()) {
case EbtDouble:
leftUnionArray[i].setUConst(static_cast<unsigned int>(rightUnionArray[i].getDConst()));
break;
- default:
+ default:
return node;
- }
+ }
break;
case EbtBool:
switch (node->getType().getBasicType()) {
case EbtDouble:
leftUnionArray[i].setBConst(rightUnionArray[i].getDConst() != 0.0);
break;
- default:
+ default:
return node;
}
break;
default:
return node;
- }
+ }
}
-
+
const TType& t = node->getType();
-
- return addConstantUnion(leftUnionArray, TType(promoteTo, t.getQualifier().storage, t.getVectorSize(), t.getMatrixCols(), t.getMatrixRows()),
+
+ return addConstantUnion(leftUnionArray, TType(promoteTo, t.getQualifier().storage, t.getVectorSize(), t.getMatrixCols(), t.getMatrixRows()),
node->getLoc());
}