From 4ba94413d304eebef7e93e09e5657f11ca9ae822 Mon Sep 17 00:00:00 2001 From: John Kessenich Date: Sun, 7 Apr 2013 02:10:55 +0000 Subject: [PATCH] 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 --- glslang/Include/BaseTypes.h | 4 +- glslang/MachineIndependent/Intermediate.cpp | 114 ++++++++++-------- glslang/MachineIndependent/ParseHelper.cpp | 2 +- glslang/MachineIndependent/glslang.y | 72 +++++------ .../MachineIndependent/localintermediate.h | 5 +- 5 files changed, 103 insertions(+), 94 deletions(-) diff --git a/glslang/Include/BaseTypes.h b/glslang/Include/BaseTypes.h index c04fb6fa..999da504 100644 --- a/glslang/Include/BaseTypes.h +++ b/glslang/Include/BaseTypes.h @@ -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 { - EpqNone, + EpqNone = 0, EpqLow, EpqMedium, EpqHigh diff --git a/glslang/MachineIndependent/Intermediate.cpp b/glslang/MachineIndependent/Intermediate.cpp index c9ea0302..117fe3c3 100644 --- a/glslang/MachineIndependent/Intermediate.cpp +++ b/glslang/MachineIndependent/Intermediate.cpp @@ -69,7 +69,7 @@ TIntermSymbol* TIntermediate::addSymbol(int id, const TString& name, const TType // // 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) { case EOpLessThan: @@ -195,9 +195,8 @@ TIntermTyped* TIntermediate::addIndex(TOperator op, TIntermTyped* base, TIntermT // // 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(); if (child == 0) { @@ -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) { case EOpConstructInt: @@ -256,15 +255,11 @@ TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermNode* childNode, return child; default: break; // some compilers want this } - - TIntermConstantUnion *childTempConstant = 0; - if (child->getAsConstantUnion()) - childTempConstant = child->getAsConstantUnion(); - + // // Make a new node for the operator. // - node = new TIntermUnary(op); + TIntermUnary* node = new TIntermUnary(op); if (line == 0) line = child->getLine(); node->setLine(line); @@ -273,16 +268,71 @@ TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermNode* childNode, if (! node->promote(infoSink)) return 0; - if (childTempConstant) { - TIntermTyped* newChild = childTempConstant->fold(op, node->getType(), infoSink); - - if (newChild) - return newChild; - } + if (child->getAsConstantUnion()) + 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 + + TIntermSequence& sequence = node->getAsAggregate()->getSequence(); + 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; + } +} + // // This is the safe way to change the operator on an aggregate, as it // does lots of error checking and fixing. Especially for establishing @@ -898,39 +948,7 @@ bool TIntermUnary::promote(TInfoSink&) return false; 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: - // TODO: functionality: uint/int versions of built-ins - // make sure all paths set the type if (operand->getBasicType() != EbtFloat) return false; diff --git a/glslang/MachineIndependent/ParseHelper.cpp b/glslang/MachineIndependent/ParseHelper.cpp index f65ff1fd..079a4959 100644 --- a/glslang/MachineIndependent/ParseHelper.cpp +++ b/glslang/MachineIndependent/ParseHelper.cpp @@ -1329,7 +1329,7 @@ TIntermTyped* TParseContext::constructBuiltIn(const TType& type, TOperator op, T return 0; } - newNode = intermediate.addUnaryMath(basicOp, node, node->getLine(), symbolTable); + newNode = intermediate.addUnaryMath(basicOp, node, node->getLine()); if (newNode == 0) { error(line, "can't convert", "constructor", ""); return 0; diff --git a/glslang/MachineIndependent/glslang.y b/glslang/MachineIndependent/glslang.y index ad1e9c0a..a3ea7a61 100644 --- a/glslang/MachineIndependent/glslang.y +++ b/glslang/MachineIndependent/glslang.y @@ -457,7 +457,7 @@ postfix_expression parseContext.variableErrorCheck($1); if (parseContext.lValueErrorCheck($2.line, "++", $1)) parseContext.recover(); - $$ = parseContext.intermediate.addUnaryMath(EOpPostIncrement, $1, $2.line, parseContext.symbolTable); + $$ = parseContext.intermediate.addUnaryMath(EOpPostIncrement, $1, $2.line); if ($$ == 0) { parseContext.unaryOpError($2.line, "++", $1->getCompleteString()); parseContext.recover(); @@ -468,7 +468,7 @@ postfix_expression parseContext.variableErrorCheck($1); if (parseContext.lValueErrorCheck($2.line, "--", $1)) parseContext.recover(); - $$ = parseContext.intermediate.addUnaryMath(EOpPostDecrement, $1, $2.line, parseContext.symbolTable); + $$ = parseContext.intermediate.addUnaryMath(EOpPostDecrement, $1, $2.line); if ($$ == 0) { parseContext.unaryOpError($2.line, "--", $1->getCompleteString()); parseContext.recover(); @@ -536,28 +536,16 @@ function_call // op = fnCandidate->getBuiltInOp(); if (builtIn && op != EOpNull) { - // // A function call mapped to a built-in operation. - // - if (fnCandidate->getParamCount() == 1) { - // - // Treat it like a built-in unary operator. - // addUnaryMath() should get the type correct on its own; - // including constness (which would differ from the prototype). - // - $$ = parseContext.intermediate.addUnaryMath(op, $1.intermNode, 0, parseContext.symbolTable); - if ($$ == 0) { - parseContext.error($1.intermNode->getLine(), " wrong operand type", "Internal Error", - "built in unary operator function. Type: %s", - static_cast($1.intermNode)->getCompleteString().c_str()); - YYERROR; - } - } else { - $$ = parseContext.intermediate.setAggregateOperator($1.intermAggregate, op, fnCandidate->getReturnType(), $1.line); + $$ = parseContext.intermediate.addBuiltInFunctionCall(op, fnCandidate->getParamCount() == 1, $1.intermNode, fnCandidate->getReturnType()); + if ($$ == 0) { + parseContext.error($1.intermNode->getLine(), " wrong operand type", "Internal Error", + "built in unary operator function. Type: %s", + static_cast($1.intermNode)->getCompleteString().c_str()); + YYERROR; } } else { // This is a real function call - $$ = parseContext.intermediate.setAggregateOperator($1.intermAggregate, EOpFunctionCall, fnCandidate->getReturnType(), $1.line); // this is how we know whether the given function is a builtIn function or a user defined function @@ -828,7 +816,7 @@ unary_expression | INC_OP unary_expression { if (parseContext.lValueErrorCheck($1.line, "++", $2)) parseContext.recover(); - $$ = parseContext.intermediate.addUnaryMath(EOpPreIncrement, $2, $1.line, parseContext.symbolTable); + $$ = parseContext.intermediate.addUnaryMath(EOpPreIncrement, $2, $1.line); if ($$ == 0) { parseContext.unaryOpError($1.line, "++", $2->getCompleteString()); parseContext.recover(); @@ -838,7 +826,7 @@ unary_expression | DEC_OP unary_expression { if (parseContext.lValueErrorCheck($1.line, "--", $2)) parseContext.recover(); - $$ = parseContext.intermediate.addUnaryMath(EOpPreDecrement, $2, $1.line, parseContext.symbolTable); + $$ = parseContext.intermediate.addUnaryMath(EOpPreDecrement, $2, $1.line); if ($$ == 0) { parseContext.unaryOpError($1.line, "--", $2->getCompleteString()); parseContext.recover(); @@ -847,7 +835,7 @@ unary_expression } | unary_operator unary_expression { if ($1.op != EOpNull) { - $$ = parseContext.intermediate.addUnaryMath($1.op, $2, $1.line, parseContext.symbolTable); + $$ = parseContext.intermediate.addUnaryMath($1.op, $2, $1.line); if ($$ == 0) { char errorOp[2] = {0, 0}; switch($1.op) { @@ -877,7 +865,7 @@ unary_operator multiplicative_expression : unary_expression { $$ = $1; } | multiplicative_expression STAR unary_expression { - $$ = parseContext.intermediate.addBinaryMath(EOpMul, $1, $3, $2.line, parseContext.symbolTable); + $$ = parseContext.intermediate.addBinaryMath(EOpMul, $1, $3, $2.line); if ($$ == 0) { parseContext.binaryOpError($2.line, "*", $1->getCompleteString(), $3->getCompleteString()); parseContext.recover(); @@ -885,7 +873,7 @@ multiplicative_expression } } | multiplicative_expression SLASH unary_expression { - $$ = parseContext.intermediate.addBinaryMath(EOpDiv, $1, $3, $2.line, parseContext.symbolTable); + $$ = parseContext.intermediate.addBinaryMath(EOpDiv, $1, $3, $2.line); if ($$ == 0) { parseContext.binaryOpError($2.line, "/", $1->getCompleteString(), $3->getCompleteString()); parseContext.recover(); @@ -893,7 +881,7 @@ multiplicative_expression } } | multiplicative_expression PERCENT unary_expression { - $$ = parseContext.intermediate.addBinaryMath(EOpMod, $1, $3, $2.line, parseContext.symbolTable); + $$ = parseContext.intermediate.addBinaryMath(EOpMod, $1, $3, $2.line); if ($$ == 0) { parseContext.binaryOpError($2.line, "%", $1->getCompleteString(), $3->getCompleteString()); parseContext.recover(); @@ -905,7 +893,7 @@ multiplicative_expression additive_expression : multiplicative_expression { $$ = $1; } | additive_expression PLUS multiplicative_expression { - $$ = parseContext.intermediate.addBinaryMath(EOpAdd, $1, $3, $2.line, parseContext.symbolTable); + $$ = parseContext.intermediate.addBinaryMath(EOpAdd, $1, $3, $2.line); if ($$ == 0) { parseContext.binaryOpError($2.line, "+", $1->getCompleteString(), $3->getCompleteString()); parseContext.recover(); @@ -913,7 +901,7 @@ additive_expression } } | additive_expression DASH multiplicative_expression { - $$ = parseContext.intermediate.addBinaryMath(EOpSub, $1, $3, $2.line, parseContext.symbolTable); + $$ = parseContext.intermediate.addBinaryMath(EOpSub, $1, $3, $2.line); if ($$ == 0) { parseContext.binaryOpError($2.line, "-", $1->getCompleteString(), $3->getCompleteString()); parseContext.recover(); @@ -926,7 +914,7 @@ shift_expression : additive_expression { $$ = $1; } | shift_expression LEFT_OP additive_expression { parseContext.fullIntegerCheck($2.line, "bit shift left"); - $$ = parseContext.intermediate.addBinaryMath(EOpLeftShift, $1, $3, $2.line, parseContext.symbolTable); + $$ = parseContext.intermediate.addBinaryMath(EOpLeftShift, $1, $3, $2.line); if ($$ == 0) { parseContext.binaryOpError($2.line, "<<", $1->getCompleteString(), $3->getCompleteString()); parseContext.recover(); @@ -935,7 +923,7 @@ shift_expression } | shift_expression RIGHT_OP additive_expression { parseContext.fullIntegerCheck($2.line, "bit shift right"); - $$ = parseContext.intermediate.addBinaryMath(EOpRightShift, $1, $3, $2.line, parseContext.symbolTable); + $$ = parseContext.intermediate.addBinaryMath(EOpRightShift, $1, $3, $2.line); if ($$ == 0) { parseContext.binaryOpError($2.line, ">>", $1->getCompleteString(), $3->getCompleteString()); parseContext.recover(); @@ -947,7 +935,7 @@ shift_expression relational_expression : shift_expression { $$ = $1; } | relational_expression LEFT_ANGLE shift_expression { - $$ = parseContext.intermediate.addBinaryMath(EOpLessThan, $1, $3, $2.line, parseContext.symbolTable); + $$ = parseContext.intermediate.addBinaryMath(EOpLessThan, $1, $3, $2.line); if ($$ == 0) { parseContext.binaryOpError($2.line, "<", $1->getCompleteString(), $3->getCompleteString()); parseContext.recover(); @@ -957,7 +945,7 @@ relational_expression } } | relational_expression RIGHT_ANGLE shift_expression { - $$ = parseContext.intermediate.addBinaryMath(EOpGreaterThan, $1, $3, $2.line, parseContext.symbolTable); + $$ = parseContext.intermediate.addBinaryMath(EOpGreaterThan, $1, $3, $2.line); if ($$ == 0) { parseContext.binaryOpError($2.line, ">", $1->getCompleteString(), $3->getCompleteString()); parseContext.recover(); @@ -967,7 +955,7 @@ relational_expression } } | relational_expression LE_OP shift_expression { - $$ = parseContext.intermediate.addBinaryMath(EOpLessThanEqual, $1, $3, $2.line, parseContext.symbolTable); + $$ = parseContext.intermediate.addBinaryMath(EOpLessThanEqual, $1, $3, $2.line); if ($$ == 0) { parseContext.binaryOpError($2.line, "<=", $1->getCompleteString(), $3->getCompleteString()); parseContext.recover(); @@ -977,7 +965,7 @@ relational_expression } } | relational_expression GE_OP shift_expression { - $$ = parseContext.intermediate.addBinaryMath(EOpGreaterThanEqual, $1, $3, $2.line, parseContext.symbolTable); + $$ = parseContext.intermediate.addBinaryMath(EOpGreaterThanEqual, $1, $3, $2.line); if ($$ == 0) { parseContext.binaryOpError($2.line, ">=", $1->getCompleteString(), $3->getCompleteString()); parseContext.recover(); @@ -991,7 +979,7 @@ relational_expression equality_expression : relational_expression { $$ = $1; } | equality_expression EQ_OP relational_expression { - $$ = parseContext.intermediate.addBinaryMath(EOpEqual, $1, $3, $2.line, parseContext.symbolTable); + $$ = parseContext.intermediate.addBinaryMath(EOpEqual, $1, $3, $2.line); if ($$ == 0) { parseContext.binaryOpError($2.line, "==", $1->getCompleteString(), $3->getCompleteString()); parseContext.recover(); @@ -1002,7 +990,7 @@ equality_expression parseContext.profileRequires($2.line, ENoProfile, 120, "GL_3DL_array_objects", "=="); } | equality_expression NE_OP relational_expression { - $$ = parseContext.intermediate.addBinaryMath(EOpNotEqual, $1, $3, $2.line, parseContext.symbolTable); + $$ = parseContext.intermediate.addBinaryMath(EOpNotEqual, $1, $3, $2.line); if ($$ == 0) { parseContext.binaryOpError($2.line, "!=", $1->getCompleteString(), $3->getCompleteString()); parseContext.recover(); @@ -1018,7 +1006,7 @@ and_expression : equality_expression { $$ = $1; } | and_expression AMPERSAND equality_expression { parseContext.fullIntegerCheck($2.line, "bitwise and"); - $$ = parseContext.intermediate.addBinaryMath(EOpAnd, $1, $3, $2.line, parseContext.symbolTable); + $$ = parseContext.intermediate.addBinaryMath(EOpAnd, $1, $3, $2.line); if ($$ == 0) { parseContext.binaryOpError($2.line, "&", $1->getCompleteString(), $3->getCompleteString()); parseContext.recover(); @@ -1031,7 +1019,7 @@ exclusive_or_expression : and_expression { $$ = $1; } | exclusive_or_expression CARET and_expression { parseContext.fullIntegerCheck($2.line, "bitwise exclusive or"); - $$ = parseContext.intermediate.addBinaryMath(EOpExclusiveOr, $1, $3, $2.line, parseContext.symbolTable); + $$ = parseContext.intermediate.addBinaryMath(EOpExclusiveOr, $1, $3, $2.line); if ($$ == 0) { parseContext.binaryOpError($2.line, "^", $1->getCompleteString(), $3->getCompleteString()); parseContext.recover(); @@ -1044,7 +1032,7 @@ inclusive_or_expression : exclusive_or_expression { $$ = $1; } | inclusive_or_expression VERTICAL_BAR exclusive_or_expression { parseContext.fullIntegerCheck($2.line, "bitwise inclusive or"); - $$ = parseContext.intermediate.addBinaryMath(EOpInclusiveOr, $1, $3, $2.line, parseContext.symbolTable); + $$ = parseContext.intermediate.addBinaryMath(EOpInclusiveOr, $1, $3, $2.line); if ($$ == 0) { parseContext.binaryOpError($2.line, "|", $1->getCompleteString(), $3->getCompleteString()); parseContext.recover(); @@ -1056,7 +1044,7 @@ inclusive_or_expression logical_and_expression : inclusive_or_expression { $$ = $1; } | logical_and_expression AND_OP inclusive_or_expression { - $$ = parseContext.intermediate.addBinaryMath(EOpLogicalAnd, $1, $3, $2.line, parseContext.symbolTable); + $$ = parseContext.intermediate.addBinaryMath(EOpLogicalAnd, $1, $3, $2.line); if ($$ == 0) { parseContext.binaryOpError($2.line, "&&", $1->getCompleteString(), $3->getCompleteString()); parseContext.recover(); @@ -1070,7 +1058,7 @@ logical_and_expression logical_xor_expression : logical_and_expression { $$ = $1; } | logical_xor_expression XOR_OP logical_and_expression { - $$ = parseContext.intermediate.addBinaryMath(EOpLogicalXor, $1, $3, $2.line, parseContext.symbolTable); + $$ = parseContext.intermediate.addBinaryMath(EOpLogicalXor, $1, $3, $2.line); if ($$ == 0) { parseContext.binaryOpError($2.line, "^^", $1->getCompleteString(), $3->getCompleteString()); parseContext.recover(); @@ -1084,7 +1072,7 @@ logical_xor_expression logical_or_expression : logical_xor_expression { $$ = $1; } | logical_or_expression OR_OP logical_xor_expression { - $$ = parseContext.intermediate.addBinaryMath(EOpLogicalOr, $1, $3, $2.line, parseContext.symbolTable); + $$ = parseContext.intermediate.addBinaryMath(EOpLogicalOr, $1, $3, $2.line); if ($$ == 0) { parseContext.binaryOpError($2.line, "||", $1->getCompleteString(), $3->getCompleteString()); parseContext.recover(); diff --git a/glslang/MachineIndependent/localintermediate.h b/glslang/MachineIndependent/localintermediate.h index f2e45121..aabab275 100644 --- a/glslang/MachineIndependent/localintermediate.h +++ b/glslang/MachineIndependent/localintermediate.h @@ -56,10 +56,11 @@ public: TIntermediate(TInfoSink& i, int v, EProfile p) : infoSink(i), version(v), profile(p) { } TIntermSymbol* addSymbol(int Id, const TString&, const TType&, TSourceLoc); 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* 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); TIntermAggregate* growAggregate(TIntermNode* left, TIntermNode* right, TSourceLoc); TIntermAggregate* makeAggregate(TIntermNode* node, TSourceLoc);