Enforce fragment precision qualifier requirement

TRAC #12156 The fragment shader has no default precision qualifier for floating-point types, so compilation should fail when it's not set explicitly globally or per declaration. Signed-off-by: Shannon Woods Signed-off-by: Daniel Koch Author: Nicolas Capens git-svn-id: https://angleproject.googlecode.com/svn/trunk@293 736b8ea6-26fd-11df-bfd4-992fa37f6226
parent 0578f81c
...@@ -12,9 +12,11 @@ ...@@ -12,9 +12,11 @@
// //
enum TPrecision enum TPrecision
{ {
EbpHigh, // These need to be kept sorted
EbpMedium, EbpUndefined,
EbpLow, EbpLow,
EbpMedium,
EbpHigh,
}; };
__inline const char* getPrecisionString(TPrecision p) __inline const char* getPrecisionString(TPrecision p)
...@@ -24,7 +26,7 @@ __inline const char* getPrecisionString(TPrecision p) ...@@ -24,7 +26,7 @@ __inline const char* getPrecisionString(TPrecision p)
case EbpHigh: return "highp"; break; case EbpHigh: return "highp"; break;
case EbpMedium: return "mediump"; break; case EbpMedium: return "mediump"; break;
case EbpLow: return "lowp"; break; case EbpLow: return "lowp"; break;
default: return "unknown precision"; default: return "mediump"; break; // Safest fallback
} }
} }
......
...@@ -23,6 +23,8 @@ void TBuiltIns::initialize() ...@@ -23,6 +23,8 @@ void TBuiltIns::initialize()
TString BuiltInFunctionsVertex; TString BuiltInFunctionsVertex;
TString BuiltInFunctionsFragment; TString BuiltInFunctionsFragment;
TString StandardUniforms; TString StandardUniforms;
TString VertexDefaultPrecision;
TString FragmentDefaultPrecision;
{ {
//============================================================================ //============================================================================
...@@ -427,19 +429,47 @@ void TBuiltIns::initialize() ...@@ -427,19 +429,47 @@ void TBuiltIns::initialize()
// Depth range in window coordinates // Depth range in window coordinates
// //
s.append(TString("struct gl_DepthRangeParameters {")); s.append(TString("struct gl_DepthRangeParameters {"));
s.append(TString(" float near;")); // n // FIXME: highp s.append(TString(" highp float near;")); // n
s.append(TString(" float far;")); // f // FIXME: highp s.append(TString(" highp float far;")); // f
s.append(TString(" float diff;")); // f - n // FIXME: highp s.append(TString(" highp float diff;")); // f - n
s.append(TString("};")); s.append(TString("};"));
s.append(TString("uniform gl_DepthRangeParameters gl_DepthRange;")); s.append(TString("uniform gl_DepthRangeParameters gl_DepthRange;"));
s.append(TString("\n")); s.append(TString("\n"));
} }
{
//============================================================================
//
// Default precision for vertex shaders.
//
//============================================================================
TString& s = VertexDefaultPrecision;
s.append(TString("precision highp int;"));
s.append(TString("precision highp float;"));
s.append(TString("\n"));
}
{
//============================================================================
//
// Default precision for fragment shaders.
//
//============================================================================
TString& s = FragmentDefaultPrecision;
s.append(TString("precision mediump int;"));
// No default precision for float in fragment shaders
s.append(TString("\n"));
}
builtInStrings[EShLangFragment].push_back(FragmentDefaultPrecision);
builtInStrings[EShLangFragment].push_back(BuiltInFunctions.c_str()); builtInStrings[EShLangFragment].push_back(BuiltInFunctions.c_str());
builtInStrings[EShLangFragment].push_back(BuiltInFunctionsFragment); builtInStrings[EShLangFragment].push_back(BuiltInFunctionsFragment);
builtInStrings[EShLangFragment].push_back(StandardUniforms); builtInStrings[EShLangFragment].push_back(StandardUniforms);
builtInStrings[EShLangVertex].push_back(VertexDefaultPrecision);
builtInStrings[EShLangVertex].push_back(BuiltInFunctions); builtInStrings[EShLangVertex].push_back(BuiltInFunctions);
builtInStrings[EShLangVertex].push_back(BuiltInFunctionsVertex); builtInStrings[EShLangVertex].push_back(BuiltInFunctionsVertex);
builtInStrings[EShLangVertex].push_back(StandardUniforms); builtInStrings[EShLangVertex].push_back(StandardUniforms);
...@@ -489,18 +519,18 @@ void IdentifyBuiltIns(EShLanguage language, TSymbolTable& symbolTable) ...@@ -489,18 +519,18 @@ void IdentifyBuiltIns(EShLanguage language, TSymbolTable& symbolTable)
switch(language) { switch(language) {
case EShLangFragment: { case EShLangFragment: {
symbolTable.insert(*new TVariable(NewPoolTString("gl_FragCoord"), TType(EbtFloat, EvqFragCoord, 4))); // FIXME: mediump symbolTable.insert(*new TVariable(NewPoolTString("gl_FragCoord"), TType(EbtFloat, EbpMedium, EvqFragCoord, 4)));
symbolTable.insert(*new TVariable(NewPoolTString("gl_FrontFacing"), TType(EbtBool, EvqFrontFacing, 1))); symbolTable.insert(*new TVariable(NewPoolTString("gl_FrontFacing"), TType(EbtBool, EbpUndefined, EvqFrontFacing, 1)));
symbolTable.insert(*new TVariable(NewPoolTString("gl_FragColor"), TType(EbtFloat, EvqFragColor, 4))); // FIXME: mediump symbolTable.insert(*new TVariable(NewPoolTString("gl_FragColor"), TType(EbtFloat, EbpMedium, EvqFragColor, 4)));
symbolTable.insert(*new TVariable(NewPoolTString("gl_FragData[gl_MaxDrawBuffers]"), TType(EbtFloat, EvqFragData, 4))); // FIXME: mediump symbolTable.insert(*new TVariable(NewPoolTString("gl_FragData[gl_MaxDrawBuffers]"), TType(EbtFloat, EbpMedium, EvqFragData, 4)));
symbolTable.insert(*new TVariable(NewPoolTString("gl_PointCoord"), TType(EbtFloat, EvqPointCoord, 2))); // FIXME: mediump symbolTable.insert(*new TVariable(NewPoolTString("gl_PointCoord"), TType(EbtFloat, EbpMedium, EvqPointCoord, 2)));
} }
break; break;
case EShLangVertex: case EShLangVertex:
symbolTable.insert(*new TVariable(NewPoolTString("gl_Position"), TType(EbtFloat, EvqPosition, 4))); // FIXME: highp symbolTable.insert(*new TVariable(NewPoolTString("gl_Position"), TType(EbtFloat, EbpHigh, EvqPosition, 4)));
symbolTable.insert(*new TVariable(NewPoolTString("gl_PointSize"), TType(EbtFloat, EvqPointSize, 1))); // FIXME: mediump symbolTable.insert(*new TVariable(NewPoolTString("gl_PointSize"), TType(EbtFloat, EbpMedium, EvqPointSize, 1)));
break; break;
default: break; default: break;
} }
...@@ -587,7 +617,7 @@ void IdentifyBuiltIns(EShLanguage language, TSymbolTable& symbolTable, const TBu ...@@ -587,7 +617,7 @@ void IdentifyBuiltIns(EShLanguage language, TSymbolTable& symbolTable, const TBu
case EShLangFragment: { case EShLangFragment: {
// Set up gl_FragData. The array size. // Set up gl_FragData. The array size.
TType fragData(EbtFloat, EvqFragColor, 4, false, true); TType fragData(EbtFloat, EbpMedium, EvqFragColor, 4, false, true);
fragData.setArraySize(resources.maxDrawBuffers); fragData.setArraySize(resources.maxDrawBuffers);
symbolTable.insert(*new TVariable(NewPoolTString("gl_FragData"), fragData)); symbolTable.insert(*new TVariable(NewPoolTString("gl_FragData"), fragData));
} }
......
...@@ -16,6 +16,15 @@ ...@@ -16,6 +16,15 @@
bool CompareStructure(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray); bool CompareStructure(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray);
TPrecision GetHighestPrecision( TPrecision left, TPrecision right, TInfoSink& infoSink ){
TPrecision highest = left > right ? left : right;
if (highest == EbpUndefined) {
infoSink.info.message(EPrefixInternalError, "Unknown or invalid precision for operands", 0);
}
return highest;
}
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
// //
// First set of functions are to help build the intermediate representation. // First set of functions are to help build the intermediate representation.
...@@ -223,7 +232,8 @@ TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermNode* childNode, ...@@ -223,7 +232,8 @@ TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermNode* childNode,
} }
if (newType != EbtVoid) { if (newType != EbtVoid) {
child = addConversion(op, TType(newType, EvqTemporary, child->getNominalSize(), child = addConversion(op, TType(newType, child->getPrecision(), EvqTemporary,
child->getNominalSize(),
child->isMatrix(), child->isMatrix(),
child->isArray()), child->isArray()),
child); child);
...@@ -420,7 +430,7 @@ TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TInt ...@@ -420,7 +430,7 @@ TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TInt
return 0; return 0;
} }
TType type(promoteTo, EvqTemporary, node->getNominalSize(), node->isMatrix(), node->isArray()); TType type(promoteTo, node->getPrecision(), EvqTemporary, node->getNominalSize(), node->isMatrix(), node->isArray());
newNode = new TIntermUnary(newOp, type); newNode = new TIntermUnary(newOp, type);
newNode->setLine(node->getLine()); newNode->setLine(node->getLine());
newNode->setOperand(node); newNode->setOperand(node);
...@@ -591,7 +601,7 @@ TIntermTyped* TIntermediate::addSwizzle(TVectorFields& fields, TSourceLoc line) ...@@ -591,7 +601,7 @@ TIntermTyped* TIntermediate::addSwizzle(TVectorFields& fields, TSourceLoc line)
for (int i = 0; i < fields.num; i++) { for (int i = 0; i < fields.num; i++) {
unionArray = new ConstantUnion[1]; unionArray = new ConstantUnion[1];
unionArray->setIConst(fields.offsets[i]); unionArray->setIConst(fields.offsets[i]);
constIntNode = addConstantUnion(unionArray, TType(EbtInt, EvqConst), line); constIntNode = addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), line);
sequenceVector.push_back(constIntNode); sequenceVector.push_back(constIntNode);
} }
...@@ -777,6 +787,9 @@ bool TIntermBinary::promote(TInfoSink& infoSink) ...@@ -777,6 +787,9 @@ bool TIntermBinary::promote(TInfoSink& infoSink)
// //
setType(left->getType()); setType(left->getType());
TPrecision highestPrecision = GetHighestPrecision(left->getPrecision(), right->getPrecision(), infoSink);
getTypePointer()->changePrecision(highestPrecision);
// //
// Array operations. // Array operations.
// //
...@@ -789,7 +802,7 @@ bool TIntermBinary::promote(TInfoSink& infoSink) ...@@ -789,7 +802,7 @@ bool TIntermBinary::promote(TInfoSink& infoSink)
// //
case EOpEqual: case EOpEqual:
case EOpNotEqual: case EOpNotEqual:
setType(TType(EbtBool)); setType(TType(EbtBool, EbpUndefined));
break; break;
// //
...@@ -824,7 +837,7 @@ bool TIntermBinary::promote(TInfoSink& infoSink) ...@@ -824,7 +837,7 @@ bool TIntermBinary::promote(TInfoSink& infoSink)
case EOpGreaterThan: case EOpGreaterThan:
case EOpLessThanEqual: case EOpLessThanEqual:
case EOpGreaterThanEqual: case EOpGreaterThanEqual:
setType(TType(EbtBool)); setType(TType(EbtBool, EbpUndefined));
break; break;
// //
...@@ -834,7 +847,7 @@ bool TIntermBinary::promote(TInfoSink& infoSink) ...@@ -834,7 +847,7 @@ bool TIntermBinary::promote(TInfoSink& infoSink)
case EOpLogicalOr: case EOpLogicalOr:
if (left->getBasicType() != EbtBool || right->getBasicType() != EbtBool) if (left->getBasicType() != EbtBool || right->getBasicType() != EbtBool)
return false; return false;
setType(TType(EbtBool)); setType(TType(EbtBool, EbpUndefined));
break; break;
// //
...@@ -866,12 +879,12 @@ bool TIntermBinary::promote(TInfoSink& infoSink) ...@@ -866,12 +879,12 @@ bool TIntermBinary::promote(TInfoSink& infoSink)
op = EOpVectorTimesMatrix; op = EOpVectorTimesMatrix;
else { else {
op = EOpMatrixTimesScalar; op = EOpMatrixTimesScalar;
setType(TType(type, EvqTemporary, size, true)); setType(TType(type, highestPrecision, EvqTemporary, size, true));
} }
} else if (left->isMatrix() && !right->isMatrix()) { } else if (left->isMatrix() && !right->isMatrix()) {
if (right->isVector()) { if (right->isVector()) {
op = EOpMatrixTimesVector; op = EOpMatrixTimesVector;
setType(TType(type, EvqTemporary, size, false)); setType(TType(type, highestPrecision, EvqTemporary, size, false));
} else { } else {
op = EOpMatrixTimesScalar; op = EOpMatrixTimesScalar;
} }
...@@ -882,7 +895,7 @@ bool TIntermBinary::promote(TInfoSink& infoSink) ...@@ -882,7 +895,7 @@ bool TIntermBinary::promote(TInfoSink& infoSink)
// leave as component product // leave as component product
} else if (left->isVector() || right->isVector()) { } else if (left->isVector() || right->isVector()) {
op = EOpVectorTimesScalar; op = EOpVectorTimesScalar;
setType(TType(type, EvqTemporary, size, false)); setType(TType(type, highestPrecision, EvqTemporary, size, false));
} }
} else { } else {
infoSink.info.message(EPrefixInternalError, "Missing elses", getLine()); infoSink.info.message(EPrefixInternalError, "Missing elses", getLine());
...@@ -911,7 +924,7 @@ bool TIntermBinary::promote(TInfoSink& infoSink) ...@@ -911,7 +924,7 @@ bool TIntermBinary::promote(TInfoSink& infoSink)
if (! left->isVector()) if (! left->isVector())
return false; return false;
op = EOpVectorTimesScalarAssign; op = EOpVectorTimesScalarAssign;
setType(TType(type, EvqTemporary, size, false)); setType(TType(type, highestPrecision, EvqTemporary, size, false));
} }
} else { } else {
infoSink.info.message(EPrefixInternalError, "Missing elses", getLine()); infoSink.info.message(EPrefixInternalError, "Missing elses", getLine());
...@@ -933,7 +946,7 @@ bool TIntermBinary::promote(TInfoSink& infoSink) ...@@ -933,7 +946,7 @@ bool TIntermBinary::promote(TInfoSink& infoSink)
left->isVector() && right->isMatrix() || left->isVector() && right->isMatrix() ||
left->getBasicType() != right->getBasicType()) left->getBasicType() != right->getBasicType())
return false; return false;
setType(TType(type, EvqTemporary, size, left->isMatrix() || right->isMatrix())); setType(TType(type, highestPrecision, EvqTemporary, size, left->isMatrix() || right->isMatrix()));
break; break;
case EOpEqual: case EOpEqual:
...@@ -946,7 +959,7 @@ bool TIntermBinary::promote(TInfoSink& infoSink) ...@@ -946,7 +959,7 @@ bool TIntermBinary::promote(TInfoSink& infoSink)
left->isVector() && right->isMatrix() || left->isVector() && right->isMatrix() ||
left->getBasicType() != right->getBasicType()) left->getBasicType() != right->getBasicType())
return false; return false;
setType(TType(EbtBool)); setType(TType(EbtBool, EbpUndefined));
break; break;
default: default:
...@@ -1192,13 +1205,13 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod ...@@ -1192,13 +1205,13 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod
assert(objectSize == 1); assert(objectSize == 1);
tempConstArray = new ConstantUnion[1]; tempConstArray = new ConstantUnion[1];
tempConstArray->setBConst(*unionArray < *rightUnionArray); tempConstArray->setBConst(*unionArray < *rightUnionArray);
returnType = TType(EbtBool, EvqConst); returnType = TType(EbtBool, EbpUndefined, EvqConst);
break; break;
case EOpGreaterThan: case EOpGreaterThan:
assert(objectSize == 1); assert(objectSize == 1);
tempConstArray = new ConstantUnion[1]; tempConstArray = new ConstantUnion[1];
tempConstArray->setBConst(*unionArray > *rightUnionArray); tempConstArray->setBConst(*unionArray > *rightUnionArray);
returnType = TType(EbtBool, EvqConst); returnType = TType(EbtBool, EbpUndefined, EvqConst);
break; break;
case EOpLessThanEqual: case EOpLessThanEqual:
{ {
...@@ -1207,7 +1220,7 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod ...@@ -1207,7 +1220,7 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod
constant.setBConst(*unionArray > *rightUnionArray); constant.setBConst(*unionArray > *rightUnionArray);
tempConstArray = new ConstantUnion[1]; tempConstArray = new ConstantUnion[1];
tempConstArray->setBConst(!constant.getBConst()); tempConstArray->setBConst(!constant.getBConst());
returnType = TType(EbtBool, EvqConst); returnType = TType(EbtBool, EbpUndefined, EvqConst);
break; break;
} }
case EOpGreaterThanEqual: case EOpGreaterThanEqual:
...@@ -1217,7 +1230,7 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod ...@@ -1217,7 +1230,7 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod
constant.setBConst(*unionArray < *rightUnionArray); constant.setBConst(*unionArray < *rightUnionArray);
tempConstArray = new ConstantUnion[1]; tempConstArray = new ConstantUnion[1];
tempConstArray->setBConst(!constant.getBConst()); tempConstArray->setBConst(!constant.getBConst());
returnType = TType(EbtBool, EvqConst); returnType = TType(EbtBool, EbpUndefined, EvqConst);
break; break;
} }
...@@ -1242,7 +1255,7 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod ...@@ -1242,7 +1255,7 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod
tempConstArray->setBConst(false); tempConstArray->setBConst(false);
} }
tempNode = new TIntermConstantUnion(tempConstArray, TType(EbtBool, EvqConst)); tempNode = new TIntermConstantUnion(tempConstArray, TType(EbtBool, EbpUndefined, EvqConst));
tempNode->setLine(getLine()); tempNode->setLine(getLine());
return tempNode; return tempNode;
...@@ -1268,7 +1281,7 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod ...@@ -1268,7 +1281,7 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod
tempConstArray->setBConst(false); tempConstArray->setBConst(false);
} }
tempNode = new TIntermConstantUnion(tempConstArray, TType(EbtBool, EvqConst)); tempNode = new TIntermConstantUnion(tempConstArray, TType(EbtBool, EbpUndefined, EvqConst));
tempNode->setLine(getLine()); tempNode->setLine(getLine());
return tempNode; return tempNode;
...@@ -1386,7 +1399,7 @@ TIntermTyped* TIntermediate::promoteConstantUnion(TBasicType promoteTo, TIntermC ...@@ -1386,7 +1399,7 @@ TIntermTyped* TIntermediate::promoteConstantUnion(TBasicType promoteTo, TIntermC
const TType& t = node->getType(); const TType& t = node->getType();
return addConstantUnion(leftUnionArray, TType(promoteTo, t.getQualifier(), t.getNominalSize(), t.isMatrix(), t.isArray()), node->getLine()); return addConstantUnion(leftUnionArray, TType(promoteTo, t.getPrecision(), t.getQualifier(), t.getNominalSize(), t.isMatrix(), t.isArray()), node->getLine());
} }
void TIntermAggregate::addToPragmaTable(const TPragmaTable& pTable) void TIntermAggregate::addToPragmaTable(const TPragmaTable& pTable)
......
...@@ -225,6 +225,24 @@ void TParseContext::binaryOpError(int line, const char* op, TString left, TStrin ...@@ -225,6 +225,24 @@ void TParseContext::binaryOpError(int line, const char* op, TString left, TStrin
op, left.c_str(), right.c_str()); op, left.c_str(), right.c_str());
} }
bool TParseContext::precisionErrorCheck(int line, TPrecision precision, TBasicType type){
switch( type ){
case EbtFloat:
if( precision == EbpUndefined ){
error( line, "No precision specified for (float)", "", "" );
return true;
}
break;
case EbtInt:
if( precision == EbpUndefined ){
error( line, "No precision specified (int)", "", "" );
return true;
}
break;
}
return false;
}
// //
// Both test and if necessary, spit out an error, to see if the node is really // 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. // an l-value that can be operated on this way.
......
...@@ -65,6 +65,7 @@ struct TParseContext { ...@@ -65,6 +65,7 @@ struct TParseContext {
void assignError(int line, const char* op, TString left, TString right); void assignError(int line, const char* op, TString left, TString right);
void unaryOpError(int line, const char* op, TString operand); void unaryOpError(int line, const char* op, TString operand);
void binaryOpError(int line, const char* op, TString left, TString right); void binaryOpError(int line, const char* op, TString left, TString right);
bool precisionErrorCheck(int line, TPrecision precision, TBasicType type);
bool lValueErrorCheck(int line, const char* op, TIntermTyped*); bool lValueErrorCheck(int line, const char* op, TIntermTyped*);
bool constErrorCheck(TIntermTyped* node); bool constErrorCheck(TIntermTyped* node);
bool integerErrorCheck(TIntermTyped* node, const char* token); bool integerErrorCheck(TIntermTyped* node, const char* token);
......
...@@ -75,7 +75,7 @@ int TType::getStructSize() const ...@@ -75,7 +75,7 @@ int TType::getStructSize() const
void TVariable::dump(TInfoSink& infoSink) const void TVariable::dump(TInfoSink& infoSink) const
{ {
infoSink.debug << getName().c_str() << ": " << type.getQualifierString() << " " << type.getBasicString(); infoSink.debug << getName().c_str() << ": " << type.getQualifierString() << " " << type.getPrecisionString() << " " << type.getBasicString();
if (type.isArray()) { if (type.isArray()) {
infoSink.debug << "[0]"; infoSink.debug << "[0]";
} }
...@@ -208,4 +208,7 @@ void TSymbolTable::copyTable(const TSymbolTable& copyOf) ...@@ -208,4 +208,7 @@ void TSymbolTable::copyTable(const TSymbolTable& copyOf)
for (unsigned int i = 0; i < copyOf.table.size(); ++i) { for (unsigned int i = 0; i < copyOf.table.size(); ++i) {
table.push_back(copyOf.table[i]->clone(remapper)); table.push_back(copyOf.table[i]->clone(remapper));
} }
for( unsigned int i = 0; i < copyOf.precisionStack.size(); i++) {
precisionStack.push_back( copyOf.precisionStack[i] );
}
} }
...@@ -129,7 +129,7 @@ class TFunction : public TSymbol { ...@@ -129,7 +129,7 @@ class TFunction : public TSymbol {
public: public:
TFunction(TOperator o) : TFunction(TOperator o) :
TSymbol(0), TSymbol(0),
returnType(TType(EbtVoid)), returnType(TType(EbtVoid, EbpUndefined)),
op(o), op(o),
defined(false) { } defined(false) { }
TFunction(const TString *name, TType& retType, TOperator tOp = EOpNull) : TFunction(const TString *name, TType& retType, TOperator tOp = EOpNull) :
...@@ -241,6 +241,7 @@ public: ...@@ -241,6 +241,7 @@ public:
TSymbolTable(TSymbolTable& symTable) TSymbolTable(TSymbolTable& symTable)
{ {
table.push_back(symTable.table[0]); table.push_back(symTable.table[0]);
precisionStack.push_back( symTable.precisionStack[0] );
uniqueId = symTable.uniqueId; uniqueId = symTable.uniqueId;
} }
...@@ -263,12 +264,14 @@ public: ...@@ -263,12 +264,14 @@ public:
void push() void push()
{ {
table.push_back(new TSymbolTableLevel); table.push_back(new TSymbolTableLevel);
precisionStack.push_back( PrecisionStackLevel() );
} }
void pop() void pop()
{ {
delete table[currentLevel()]; delete table[currentLevel()];
table.pop_back(); table.pop_back();
precisionStack.pop_back();
} }
bool insert(TSymbol& symbol) bool insert(TSymbol& symbol)
...@@ -299,11 +302,37 @@ public: ...@@ -299,11 +302,37 @@ public:
void dump(TInfoSink &infoSink) const; void dump(TInfoSink &infoSink) const;
void copyTable(const TSymbolTable& copyOf); void copyTable(const TSymbolTable& copyOf);
void setDefaultPrecision( TBasicType type, TPrecision prec ){
if( type != EbtFloat && type != EbtInt ) return; // Only set default precision for int/float
int indexOfLastElement = static_cast<int>(precisionStack.size()) - 1;
precisionStack[indexOfLastElement][type] = prec; // Uses map operator [], overwrites the current value
}
// Searches down the precisionStack for a precision qualifier for the specified TBasicType
TPrecision getDefaultPrecision( TBasicType type){
if( type != EbtFloat && type != EbtInt ) return EbpUndefined;
int level = static_cast<int>(precisionStack.size()) - 1;
assert( level >= 0); // Just to be safe. Should not happen.
PrecisionStackLevel::iterator it;
TPrecision prec = EbpUndefined; // If we dont find anything we return this. Should we error check this?
while( level >= 0 ){
it = precisionStack[level].find( type );
if( it != precisionStack[level].end() ){
prec = (*it).second;
break;
}
level--;
}
return prec;
}
protected: protected:
int currentLevel() const { return static_cast<int>(table.size()) - 1; } int currentLevel() const { return static_cast<int>(table.size()) - 1; }
bool atDynamicBuiltInLevel() { return table.size() == 2; } bool atDynamicBuiltInLevel() { return table.size() == 2; }
std::vector<TSymbolTableLevel*> table; std::vector<TSymbolTableLevel*> table;
typedef std::map< TBasicType, TPrecision > PrecisionStackLevel;
std::vector< PrecisionStackLevel > precisionStack;
int uniqueId; // for unique identification in code generation int uniqueId; // for unique identification in code generation
}; };
......
...@@ -51,7 +51,7 @@ public: ...@@ -51,7 +51,7 @@ public:
{ {
type = bt; type = bt;
qualifier = q; qualifier = q;
precision = EbpHigh; precision = EbpUndefined;
size = 1; size = 1;
matrix = false; matrix = false;
array = false; array = false;
...@@ -60,11 +60,6 @@ public: ...@@ -60,11 +60,6 @@ public:
line = ln; line = ln;
} }
void setPrecision(TPrecision pcs)
{
precision = pcs;
}
void setAggregate(int s, bool m = false) void setAggregate(int s, bool m = false)
{ {
size = s; size = s;
...@@ -86,7 +81,7 @@ typedef TMap<TTypeList*, TTypeList*>::iterator TStructureMapIterator; ...@@ -86,7 +81,7 @@ typedef TMap<TTypeList*, TTypeList*>::iterator TStructureMapIterator;
class TType { class TType {
public: public:
POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator) POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
explicit TType(TBasicType t, TQualifier q = EvqTemporary, int s = 1, bool m = false, bool a = false, TPrecision p = EbpHigh) : explicit TType(TBasicType t, TPrecision p, TQualifier q = EvqTemporary, int s = 1, bool m = false, bool a = false) :
type(t), precision(p), qualifier(q), size(s), matrix(m), array(a), arraySize(0), type(t), precision(p), qualifier(q), size(s), matrix(m), array(a), arraySize(0),
structure(0), structureSize(0), maxArraySize(0), arrayInformationType(0), fieldName(0), mangled(0), typeName(0) structure(0), structureSize(0), maxArraySize(0), arrayInformationType(0), fieldName(0), mangled(0), typeName(0)
{ } { }
...@@ -99,7 +94,7 @@ public: ...@@ -99,7 +94,7 @@ public:
typeName = NewPoolTString(p.userDef->getTypeName().c_str()); typeName = NewPoolTString(p.userDef->getTypeName().c_str());
} }
} }
explicit TType(TTypeList* userDef, const TString& n, TPrecision p = EbpHigh) : explicit TType(TTypeList* userDef, const TString& n, TPrecision p = EbpUndefined) :
type(EbtStruct), precision(p), qualifier(EvqTemporary), size(1), matrix(false), array(false), arraySize(0), type(EbtStruct), precision(p), qualifier(EvqTemporary), size(1), matrix(false), array(false), arraySize(0),
structure(userDef), structureSize(0), maxArraySize(0), arrayInformationType(0), fieldName(0), mangled(0) { structure(userDef), structureSize(0), maxArraySize(0), arrayInformationType(0), fieldName(0), mangled(0) {
typeName = NewPoolTString(n.c_str()); typeName = NewPoolTString(n.c_str());
......
...@@ -41,7 +41,7 @@ TString TType::getCompleteString() const ...@@ -41,7 +41,7 @@ TString TType::getCompleteString() const
char *p = &buf[0]; char *p = &buf[0];
if (qualifier != EvqTemporary && qualifier != EvqGlobal) if (qualifier != EvqTemporary && qualifier != EvqGlobal)
p += sprintf(p, "%s ", getQualifierString()); p += sprintf(p, "%s %s ", getQualifierString(), getPrecisionString());
if (array) if (array)
p += sprintf(p, "array of "); p += sprintf(p, "array of ");
if (matrix) if (matrix)
......
...@@ -238,6 +238,7 @@ public: ...@@ -238,6 +238,7 @@ public:
virtual TBasicType getBasicType() const { return type.getBasicType(); } virtual TBasicType getBasicType() const { return type.getBasicType(); }
virtual TQualifier getQualifier() const { return type.getQualifier(); } virtual TQualifier getQualifier() const { return type.getQualifier(); }
virtual TPrecision getPrecision() const { return type.getPrecision(); }
virtual int getNominalSize() const { return type.getNominalSize(); } virtual int getNominalSize() const { return type.getNominalSize(); }
virtual int getSize() const { return type.getInstanceSize(); } virtual int getSize() const { return type.getInstanceSize(); }
virtual bool isMatrix() const { return type.isMatrix(); } virtual bool isMatrix() const { return type.isMatrix(); }
...@@ -334,7 +335,7 @@ public: ...@@ -334,7 +335,7 @@ public:
bool isConstructor() const; bool isConstructor() const;
virtual bool promote(TInfoSink&) { return true; } virtual bool promote(TInfoSink&) { return true; }
protected: protected:
TIntermOperator(TOperator o) : TIntermTyped(TType(EbtFloat)), op(o) {} TIntermOperator(TOperator o) : TIntermTyped(TType(EbtFloat, EbpUndefined)), op(o) {}
TIntermOperator(TOperator o, TType& t) : TIntermTyped(t), op(o) {} TIntermOperator(TOperator o, TType& t) : TIntermTyped(t), op(o) {}
TOperator op; TOperator op;
}; };
...@@ -416,7 +417,7 @@ protected: ...@@ -416,7 +417,7 @@ protected:
class TIntermSelection : public TIntermTyped { class TIntermSelection : public TIntermTyped {
public: public:
TIntermSelection(TIntermTyped* cond, TIntermNode* trueB, TIntermNode* falseB) : TIntermSelection(TIntermTyped* cond, TIntermNode* trueB, TIntermNode* falseB) :
TIntermTyped(TType(EbtVoid)), condition(cond), trueBlock(trueB), falseBlock(falseB) {} TIntermTyped(TType(EbtVoid, EbpUndefined)), condition(cond), trueBlock(trueB), falseBlock(falseB) {}
TIntermSelection(TIntermTyped* cond, TIntermNode* trueB, TIntermNode* falseB, const TType& type) : TIntermSelection(TIntermTyped* cond, TIntermNode* trueB, TIntermNode* falseB, const TType& type) :
TIntermTyped(type), condition(cond), trueBlock(trueB), falseBlock(falseB) {} TIntermTyped(type), condition(cond), trueBlock(trueB), falseBlock(falseB) {}
virtual void traverse(TIntermTraverser*); virtual void traverse(TIntermTraverser*);
......
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