Commit 4ba94413 by John Kessenich

Split out the unary-argument built-in function path from the addUnaryMath()…

Split out the unary-argument built-in function path from the addUnaryMath() path, allowing the return types to be treated correctly without any special casing. Also, implement the correct precision qualifier propagation rules for built-in functions mapped to operators. git-svn-id: https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/tools/glslang@21062 e7fa87d3-cd2b-0410-9028-fcbf551c1848
parent ebeeece6
...@@ -124,8 +124,10 @@ __inline const char* getStorageQualifierString(TStorageQualifier q) ...@@ -124,8 +124,10 @@ __inline const char* getStorageQualifierString(TStorageQualifier q)
} }
} }
// In this enum, order matters; users can assume higher precision is a bigger value
// and EpqNone is 0.
enum TPrecisionQualifier { enum TPrecisionQualifier {
EpqNone, EpqNone = 0,
EpqLow, EpqLow,
EpqMedium, EpqMedium,
EpqHigh EpqHigh
......
...@@ -69,7 +69,7 @@ TIntermSymbol* TIntermediate::addSymbol(int id, const TString& name, const TType ...@@ -69,7 +69,7 @@ TIntermSymbol* TIntermediate::addSymbol(int id, const TString& name, const TType
// //
// Returns the added node. // Returns the added node.
// //
TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc line, TSymbolTable& symbolTable) TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc line)
{ {
switch (op) { switch (op) {
case EOpLessThan: case EOpLessThan:
...@@ -195,9 +195,8 @@ TIntermTyped* TIntermediate::addIndex(TOperator op, TIntermTyped* base, TIntermT ...@@ -195,9 +195,8 @@ TIntermTyped* TIntermediate::addIndex(TOperator op, TIntermTyped* base, TIntermT
// //
// Returns the added node. // Returns the added node.
// //
TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermNode* childNode, TSourceLoc line, TSymbolTable& symbolTable) TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermNode* childNode, TSourceLoc line)
{ {
TIntermUnary* node;
TIntermTyped* child = childNode->getAsTyped(); TIntermTyped* child = childNode->getAsTyped();
if (child == 0) { if (child == 0) {
...@@ -245,7 +244,7 @@ TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermNode* childNode, ...@@ -245,7 +244,7 @@ TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermNode* childNode,
} }
// //
// For constructors, we are now done, it's all in the conversion. // For constructors, we are now done, it was all in the conversion.
// //
switch (op) { switch (op) {
case EOpConstructInt: case EOpConstructInt:
...@@ -257,14 +256,10 @@ TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermNode* childNode, ...@@ -257,14 +256,10 @@ TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermNode* childNode,
default: break; // some compilers want this default: break; // some compilers want this
} }
TIntermConstantUnion *childTempConstant = 0;
if (child->getAsConstantUnion())
childTempConstant = child->getAsConstantUnion();
// //
// Make a new node for the operator. // Make a new node for the operator.
// //
node = new TIntermUnary(op); TIntermUnary* node = new TIntermUnary(op);
if (line == 0) if (line == 0)
line = child->getLine(); line = child->getLine();
node->setLine(line); node->setLine(line);
...@@ -273,14 +268,69 @@ TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermNode* childNode, ...@@ -273,14 +268,69 @@ TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermNode* childNode,
if (! node->promote(infoSink)) if (! node->promote(infoSink))
return 0; return 0;
if (childTempConstant) { if (child->getAsConstantUnion())
TIntermTyped* newChild = childTempConstant->fold(op, node->getType(), infoSink); return child->getAsConstantUnion()->fold(op, node->getType(), infoSink);
return node;
}
TIntermTyped* TIntermediate::addBuiltInFunctionCall(TOperator op, bool unary, TIntermNode* childNode, const TType& returnType)
{
if (unary) {
//
// 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) {
infoSink.info.message(EPrefixInternalError, "Bad type in AddUnaryMath", child->getLine());
return 0;
}
if (child->getAsConstantUnion())
return child->getAsConstantUnion()->fold(op, returnType, infoSink);
TIntermUnary* node = new TIntermUnary(op);
node->setLine(child->getLine());
node->setOperand(child);
node->setType(returnType);
// propagate precision up from child
if (returnType.getQualifier().precision == EpqNone && profile == EEsProfile)
node->getQualifier().precision = child->getQualifier().precision;
// propagate precision down to child
if (node->getQualifier().precision != EpqNone &&
child->getQualifier().precision == EpqNone)
child->getQualifier().precision = node->getQualifier().precision;
return node;
} else {
// setAggregateOperater() calls fold() for constant folding
TIntermTyped* node = setAggregateOperator(childNode, op, returnType, childNode->getLine());
if (returnType.getQualifier().precision == EpqNone && profile == EEsProfile) {
// get maximum precision from arguments, for the built-in's return precision
if (newChild) TIntermSequence& sequence = node->getAsAggregate()->getSequence();
return newChild; TPrecisionQualifier maxPq = EpqNone;
for (unsigned int arg = 0; arg < sequence.size(); ++arg)
maxPq = std::max(maxPq, sequence[arg]->getAsTyped()->getQualifier().precision);
node->getQualifier().precision = maxPq;
}
if (node->getQualifier().precision != EpqNone) {
TIntermSequence& sequence = node->getAsAggregate()->getSequence();
for (unsigned int arg = 0; arg < sequence.size(); ++arg)
if (sequence[arg]->getAsTyped()->getQualifier().precision == EpqNone)
sequence[arg]->getAsTyped()->getQualifier().precision = node->getQualifier().precision;
} }
return node; return node;
}
} }
// //
...@@ -898,39 +948,7 @@ bool TIntermUnary::promote(TInfoSink&) ...@@ -898,39 +948,7 @@ bool TIntermUnary::promote(TInfoSink&)
return false; return false;
break; break;
//
// Operators for built-ins are already type checked against their prototype.
// Special case the non-float ones, just so we don't give an error.
//
case EOpAny:
case EOpAll:
setType(TType(EbtBool));
return true;
case EOpVectorLogicalNot:
break;
case EOpLength:
setType(TType(EbtFloat, EvqTemporary, operand->getQualifier().precision));
return true;
case EOpTranspose:
setType(TType(operand->getType().getBasicType(), EvqTemporary, operand->getQualifier().precision, 0,
operand->getType().getMatrixRows(),
operand->getType().getMatrixCols()));
return true;
case EOpDeterminant:
setType(TType(operand->getType().getBasicType(), EvqTemporary, operand->getQualifier().precision));
return true;
default: default:
// TODO: functionality: uint/int versions of built-ins
// make sure all paths set the type
if (operand->getBasicType() != EbtFloat) if (operand->getBasicType() != EbtFloat)
return false; return false;
......
...@@ -1329,7 +1329,7 @@ TIntermTyped* TParseContext::constructBuiltIn(const TType& type, TOperator op, T ...@@ -1329,7 +1329,7 @@ TIntermTyped* TParseContext::constructBuiltIn(const TType& type, TOperator op, T
return 0; return 0;
} }
newNode = intermediate.addUnaryMath(basicOp, node, node->getLine(), symbolTable); newNode = intermediate.addUnaryMath(basicOp, node, node->getLine());
if (newNode == 0) { if (newNode == 0) {
error(line, "can't convert", "constructor", ""); error(line, "can't convert", "constructor", "");
return 0; return 0;
......
...@@ -56,10 +56,11 @@ public: ...@@ -56,10 +56,11 @@ public:
TIntermediate(TInfoSink& i, int v, EProfile p) : infoSink(i), version(v), profile(p) { } TIntermediate(TInfoSink& i, int v, EProfile p) : infoSink(i), version(v), profile(p) { }
TIntermSymbol* addSymbol(int Id, const TString&, const TType&, TSourceLoc); TIntermSymbol* addSymbol(int Id, const TString&, const TType&, TSourceLoc);
TIntermTyped* addConversion(TOperator, const TType&, TIntermTyped*); TIntermTyped* addConversion(TOperator, const TType&, TIntermTyped*);
TIntermTyped* addBinaryMath(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc, TSymbolTable&); TIntermTyped* addBinaryMath(TOperator, TIntermTyped* left, TIntermTyped* right, TSourceLoc);
TIntermTyped* addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc); TIntermTyped* addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc);
TIntermTyped* addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, TSourceLoc); TIntermTyped* addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, TSourceLoc);
TIntermTyped* addUnaryMath(TOperator op, TIntermNode* child, TSourceLoc, TSymbolTable&); TIntermTyped* addUnaryMath(TOperator, TIntermNode* child, TSourceLoc);
TIntermTyped* addBuiltInFunctionCall(TOperator, bool unary, TIntermNode*, const TType& returnType);
bool canImplicitlyPromote(TBasicType from, TBasicType to); bool canImplicitlyPromote(TBasicType from, TBasicType to);
TIntermAggregate* growAggregate(TIntermNode* left, TIntermNode* right, TSourceLoc); TIntermAggregate* growAggregate(TIntermNode* left, TIntermNode* right, TSourceLoc);
TIntermAggregate* makeAggregate(TIntermNode* node, TSourceLoc); TIntermAggregate* makeAggregate(TIntermNode* node, TSourceLoc);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment