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
diff --git a/src/compiler/BaseTypes.h b/src/compiler/BaseTypes.h
index 93df646..cb646fc 100644
--- a/src/compiler/BaseTypes.h
+++ b/src/compiler/BaseTypes.h
@@ -12,9 +12,11 @@
//
enum TPrecision
{
- EbpHigh,
- EbpMedium,
+ // These need to be kept sorted
+ EbpUndefined,
EbpLow,
+ EbpMedium,
+ EbpHigh,
};
__inline const char* getPrecisionString(TPrecision p)
@@ -24,7 +26,7 @@
case EbpHigh: return "highp"; break;
case EbpMedium: return "mediump"; break;
case EbpLow: return "lowp"; break;
- default: return "unknown precision";
+ default: return "mediump"; break; // Safest fallback
}
}
diff --git a/src/compiler/Initialize.cpp b/src/compiler/Initialize.cpp
index 306ac09..ab61528 100644
--- a/src/compiler/Initialize.cpp
+++ b/src/compiler/Initialize.cpp
@@ -23,6 +23,8 @@
TString BuiltInFunctionsVertex;
TString BuiltInFunctionsFragment;
TString StandardUniforms;
+ TString VertexDefaultPrecision;
+ TString FragmentDefaultPrecision;
{
//============================================================================
@@ -427,19 +429,47 @@
// Depth range in window coordinates
//
s.append(TString("struct gl_DepthRangeParameters {"));
- s.append(TString(" float near;")); // n // FIXME: highp
- s.append(TString(" float far;")); // f // FIXME: highp
- s.append(TString(" float diff;")); // f - n // FIXME: highp
+ s.append(TString(" highp float near;")); // n
+ s.append(TString(" highp float far;")); // f
+ s.append(TString(" highp float diff;")); // f - n
s.append(TString("};"));
s.append(TString("uniform gl_DepthRangeParameters gl_DepthRange;"));
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(BuiltInFunctionsFragment);
builtInStrings[EShLangFragment].push_back(StandardUniforms);
-
+
+ builtInStrings[EShLangVertex].push_back(VertexDefaultPrecision);
builtInStrings[EShLangVertex].push_back(BuiltInFunctions);
builtInStrings[EShLangVertex].push_back(BuiltInFunctionsVertex);
builtInStrings[EShLangVertex].push_back(StandardUniforms);
@@ -489,18 +519,18 @@
switch(language) {
case EShLangFragment: {
- symbolTable.insert(*new TVariable(NewPoolTString("gl_FragCoord"), TType(EbtFloat, EvqFragCoord, 4))); // FIXME: mediump
- symbolTable.insert(*new TVariable(NewPoolTString("gl_FrontFacing"), TType(EbtBool, EvqFrontFacing, 1)));
- symbolTable.insert(*new TVariable(NewPoolTString("gl_FragColor"), TType(EbtFloat, EvqFragColor, 4))); // FIXME: mediump
- symbolTable.insert(*new TVariable(NewPoolTString("gl_FragData[gl_MaxDrawBuffers]"), TType(EbtFloat, EvqFragData, 4))); // FIXME: mediump
- symbolTable.insert(*new TVariable(NewPoolTString("gl_PointCoord"), TType(EbtFloat, EvqPointCoord, 2))); // FIXME: mediump
+ symbolTable.insert(*new TVariable(NewPoolTString("gl_FragCoord"), TType(EbtFloat, EbpMedium, EvqFragCoord, 4)));
+ symbolTable.insert(*new TVariable(NewPoolTString("gl_FrontFacing"), TType(EbtBool, EbpUndefined, EvqFrontFacing, 1)));
+ symbolTable.insert(*new TVariable(NewPoolTString("gl_FragColor"), TType(EbtFloat, EbpMedium, EvqFragColor, 4)));
+ symbolTable.insert(*new TVariable(NewPoolTString("gl_FragData[gl_MaxDrawBuffers]"), TType(EbtFloat, EbpMedium, EvqFragData, 4)));
+ symbolTable.insert(*new TVariable(NewPoolTString("gl_PointCoord"), TType(EbtFloat, EbpMedium, EvqPointCoord, 2)));
}
break;
case EShLangVertex:
- symbolTable.insert(*new TVariable(NewPoolTString("gl_Position"), TType(EbtFloat, EvqPosition, 4))); // FIXME: highp
- symbolTable.insert(*new TVariable(NewPoolTString("gl_PointSize"), TType(EbtFloat, EvqPointSize, 1))); // FIXME: mediump
+ symbolTable.insert(*new TVariable(NewPoolTString("gl_Position"), TType(EbtFloat, EbpHigh, EvqPosition, 4)));
+ symbolTable.insert(*new TVariable(NewPoolTString("gl_PointSize"), TType(EbtFloat, EbpMedium, EvqPointSize, 1)));
break;
default: break;
}
@@ -587,7 +617,7 @@
case EShLangFragment: {
// 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);
symbolTable.insert(*new TVariable(NewPoolTString("gl_FragData"), fragData));
}
diff --git a/src/compiler/Intermediate.cpp b/src/compiler/Intermediate.cpp
index 4a228f5..f1044b4 100644
--- a/src/compiler/Intermediate.cpp
+++ b/src/compiler/Intermediate.cpp
@@ -16,6 +16,15 @@
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.
@@ -223,7 +232,8 @@
}
if (newType != EbtVoid) {
- child = addConversion(op, TType(newType, EvqTemporary, child->getNominalSize(),
+ child = addConversion(op, TType(newType, child->getPrecision(), EvqTemporary,
+ child->getNominalSize(),
child->isMatrix(),
child->isArray()),
child);
@@ -420,7 +430,7 @@
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->setLine(node->getLine());
newNode->setOperand(node);
@@ -591,7 +601,7 @@
for (int i = 0; i < fields.num; i++) {
unionArray = new ConstantUnion[1];
unionArray->setIConst(fields.offsets[i]);
- constIntNode = addConstantUnion(unionArray, TType(EbtInt, EvqConst), line);
+ constIntNode = addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), line);
sequenceVector.push_back(constIntNode);
}
@@ -777,6 +787,9 @@
//
setType(left->getType());
+ TPrecision highestPrecision = GetHighestPrecision(left->getPrecision(), right->getPrecision(), infoSink);
+ getTypePointer()->changePrecision(highestPrecision);
+
//
// Array operations.
//
@@ -789,7 +802,7 @@
//
case EOpEqual:
case EOpNotEqual:
- setType(TType(EbtBool));
+ setType(TType(EbtBool, EbpUndefined));
break;
//
@@ -824,7 +837,7 @@
case EOpGreaterThan:
case EOpLessThanEqual:
case EOpGreaterThanEqual:
- setType(TType(EbtBool));
+ setType(TType(EbtBool, EbpUndefined));
break;
//
@@ -834,7 +847,7 @@
case EOpLogicalOr:
if (left->getBasicType() != EbtBool || right->getBasicType() != EbtBool)
return false;
- setType(TType(EbtBool));
+ setType(TType(EbtBool, EbpUndefined));
break;
//
@@ -866,12 +879,12 @@
op = EOpVectorTimesMatrix;
else {
op = EOpMatrixTimesScalar;
- setType(TType(type, EvqTemporary, size, true));
+ setType(TType(type, highestPrecision, EvqTemporary, size, true));
}
} else if (left->isMatrix() && !right->isMatrix()) {
if (right->isVector()) {
op = EOpMatrixTimesVector;
- setType(TType(type, EvqTemporary, size, false));
+ setType(TType(type, highestPrecision, EvqTemporary, size, false));
} else {
op = EOpMatrixTimesScalar;
}
@@ -882,7 +895,7 @@
// leave as component product
} else if (left->isVector() || right->isVector()) {
op = EOpVectorTimesScalar;
- setType(TType(type, EvqTemporary, size, false));
+ setType(TType(type, highestPrecision, EvqTemporary, size, false));
}
} else {
infoSink.info.message(EPrefixInternalError, "Missing elses", getLine());
@@ -911,7 +924,7 @@
if (! left->isVector())
return false;
op = EOpVectorTimesScalarAssign;
- setType(TType(type, EvqTemporary, size, false));
+ setType(TType(type, highestPrecision, EvqTemporary, size, false));
}
} else {
infoSink.info.message(EPrefixInternalError, "Missing elses", getLine());
@@ -933,7 +946,7 @@
left->isVector() && right->isMatrix() ||
left->getBasicType() != right->getBasicType())
return false;
- setType(TType(type, EvqTemporary, size, left->isMatrix() || right->isMatrix()));
+ setType(TType(type, highestPrecision, EvqTemporary, size, left->isMatrix() || right->isMatrix()));
break;
case EOpEqual:
@@ -946,7 +959,7 @@
left->isVector() && right->isMatrix() ||
left->getBasicType() != right->getBasicType())
return false;
- setType(TType(EbtBool));
+ setType(TType(EbtBool, EbpUndefined));
break;
default:
@@ -1192,13 +1205,13 @@
assert(objectSize == 1);
tempConstArray = new ConstantUnion[1];
tempConstArray->setBConst(*unionArray < *rightUnionArray);
- returnType = TType(EbtBool, EvqConst);
+ returnType = TType(EbtBool, EbpUndefined, EvqConst);
break;
case EOpGreaterThan:
assert(objectSize == 1);
tempConstArray = new ConstantUnion[1];
tempConstArray->setBConst(*unionArray > *rightUnionArray);
- returnType = TType(EbtBool, EvqConst);
+ returnType = TType(EbtBool, EbpUndefined, EvqConst);
break;
case EOpLessThanEqual:
{
@@ -1207,7 +1220,7 @@
constant.setBConst(*unionArray > *rightUnionArray);
tempConstArray = new ConstantUnion[1];
tempConstArray->setBConst(!constant.getBConst());
- returnType = TType(EbtBool, EvqConst);
+ returnType = TType(EbtBool, EbpUndefined, EvqConst);
break;
}
case EOpGreaterThanEqual:
@@ -1217,7 +1230,7 @@
constant.setBConst(*unionArray < *rightUnionArray);
tempConstArray = new ConstantUnion[1];
tempConstArray->setBConst(!constant.getBConst());
- returnType = TType(EbtBool, EvqConst);
+ returnType = TType(EbtBool, EbpUndefined, EvqConst);
break;
}
@@ -1242,7 +1255,7 @@
tempConstArray->setBConst(false);
}
- tempNode = new TIntermConstantUnion(tempConstArray, TType(EbtBool, EvqConst));
+ tempNode = new TIntermConstantUnion(tempConstArray, TType(EbtBool, EbpUndefined, EvqConst));
tempNode->setLine(getLine());
return tempNode;
@@ -1268,7 +1281,7 @@
tempConstArray->setBConst(false);
}
- tempNode = new TIntermConstantUnion(tempConstArray, TType(EbtBool, EvqConst));
+ tempNode = new TIntermConstantUnion(tempConstArray, TType(EbtBool, EbpUndefined, EvqConst));
tempNode->setLine(getLine());
return tempNode;
@@ -1386,7 +1399,7 @@
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)
diff --git a/src/compiler/ParseHelper.cpp b/src/compiler/ParseHelper.cpp
index 7141b0c..396e87a 100644
--- a/src/compiler/ParseHelper.cpp
+++ b/src/compiler/ParseHelper.cpp
@@ -225,6 +225,24 @@
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
// an l-value that can be operated on this way.
diff --git a/src/compiler/ParseHelper.h b/src/compiler/ParseHelper.h
index 995f918..718ff32 100644
--- a/src/compiler/ParseHelper.h
+++ b/src/compiler/ParseHelper.h
@@ -65,6 +65,7 @@
void assignError(int line, const char* op, TString left, TString right);
void unaryOpError(int line, const char* op, TString operand);
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 constErrorCheck(TIntermTyped* node);
bool integerErrorCheck(TIntermTyped* node, const char* token);
diff --git a/src/compiler/SymbolTable.cpp b/src/compiler/SymbolTable.cpp
index 483204c..142763d 100644
--- a/src/compiler/SymbolTable.cpp
+++ b/src/compiler/SymbolTable.cpp
@@ -75,7 +75,7 @@
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()) {
infoSink.debug << "[0]";
}
@@ -208,4 +208,7 @@
for (unsigned int i = 0; i < copyOf.table.size(); ++i) {
table.push_back(copyOf.table[i]->clone(remapper));
}
+ for( unsigned int i = 0; i < copyOf.precisionStack.size(); i++) {
+ precisionStack.push_back( copyOf.precisionStack[i] );
+ }
}
diff --git a/src/compiler/SymbolTable.h b/src/compiler/SymbolTable.h
index f58cdb8..fa6e64d 100644
--- a/src/compiler/SymbolTable.h
+++ b/src/compiler/SymbolTable.h
@@ -129,7 +129,7 @@
public:
TFunction(TOperator o) :
TSymbol(0),
- returnType(TType(EbtVoid)),
+ returnType(TType(EbtVoid, EbpUndefined)),
op(o),
defined(false) { }
TFunction(const TString *name, TType& retType, TOperator tOp = EOpNull) :
@@ -241,6 +241,7 @@
TSymbolTable(TSymbolTable& symTable)
{
table.push_back(symTable.table[0]);
+ precisionStack.push_back( symTable.precisionStack[0] );
uniqueId = symTable.uniqueId;
}
@@ -263,12 +264,14 @@
void push()
{
table.push_back(new TSymbolTableLevel);
+ precisionStack.push_back( PrecisionStackLevel() );
}
void pop()
{
delete table[currentLevel()];
table.pop_back();
+ precisionStack.pop_back();
}
bool insert(TSymbol& symbol)
@@ -299,11 +302,37 @@
void dump(TInfoSink &infoSink) const;
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:
int currentLevel() const { return static_cast<int>(table.size()) - 1; }
bool atDynamicBuiltInLevel() { return table.size() == 2; }
std::vector<TSymbolTableLevel*> table;
+ typedef std::map< TBasicType, TPrecision > PrecisionStackLevel;
+ std::vector< PrecisionStackLevel > precisionStack;
int uniqueId; // for unique identification in code generation
};
diff --git a/src/compiler/Types.h b/src/compiler/Types.h
index 0ad9d63..fca0ac1 100644
--- a/src/compiler/Types.h
+++ b/src/compiler/Types.h
@@ -51,7 +51,7 @@
{
type = bt;
qualifier = q;
- precision = EbpHigh;
+ precision = EbpUndefined;
size = 1;
matrix = false;
array = false;
@@ -60,11 +60,6 @@
line = ln;
}
- void setPrecision(TPrecision pcs)
- {
- precision = pcs;
- }
-
void setAggregate(int s, bool m = false)
{
size = s;
@@ -86,7 +81,7 @@
class TType {
public:
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),
structure(0), structureSize(0), maxArraySize(0), arrayInformationType(0), fieldName(0), mangled(0), typeName(0)
{ }
@@ -99,7 +94,7 @@
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),
structure(userDef), structureSize(0), maxArraySize(0), arrayInformationType(0), fieldName(0), mangled(0) {
typeName = NewPoolTString(n.c_str());
diff --git a/src/compiler/glslang.y b/src/compiler/glslang.y
index 700bd00..9ab9962 100644
--- a/src/compiler/glslang.y
+++ b/src/compiler/glslang.y
@@ -187,7 +187,7 @@
if (symbol == 0) {
parseContext->error($1.line, "undeclared identifier", $1.string->c_str(), "");
parseContext->recover();
- TType type(EbtFloat);
+ TType type(EbtFloat, EbpUndefined);
TVariable* fakeVariable = new TVariable($1.string, type);
parseContext->symbolTable.insert(*fakeVariable);
variable = fakeVariable;
@@ -229,17 +229,17 @@
}
ConstantUnion *unionArray = new ConstantUnion[1];
unionArray->setIConst($1.i);
- $$ = parseContext->intermediate.addConstantUnion(unionArray, TType(EbtInt, EvqConst), $1.line);
+ $$ = parseContext->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), $1.line);
}
| FLOATCONSTANT {
ConstantUnion *unionArray = new ConstantUnion[1];
unionArray->setFConst($1.f);
- $$ = parseContext->intermediate.addConstantUnion(unionArray, TType(EbtFloat, EvqConst), $1.line);
+ $$ = parseContext->intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpUndefined, EvqConst), $1.line);
}
| BOOLCONSTANT {
ConstantUnion *unionArray = new ConstantUnion[1];
unionArray->setBConst($1.b);
- $$ = parseContext->intermediate.addConstantUnion(unionArray, TType(EbtBool, EvqConst), $1.line);
+ $$ = parseContext->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $1.line);
}
| LEFT_PAREN expression RIGHT_PAREN {
$$ = $2;
@@ -303,23 +303,23 @@
if ($$ == 0) {
ConstantUnion *unionArray = new ConstantUnion[1];
unionArray->setFConst(0.0f);
- $$ = parseContext->intermediate.addConstantUnion(unionArray, TType(EbtFloat, EvqConst), $2.line);
+ $$ = parseContext->intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpHigh, EvqConst), $2.line);
} else if ($1->isArray()) {
if ($1->getType().getStruct())
$$->setType(TType($1->getType().getStruct(), $1->getType().getTypeName()));
else
- $$->setType(TType($1->getBasicType(), EvqTemporary, $1->getNominalSize(), $1->isMatrix()));
+ $$->setType(TType($1->getBasicType(), $1->getPrecision(), EvqTemporary, $1->getNominalSize(), $1->isMatrix()));
if ($1->getType().getQualifier() == EvqConst)
$$->getTypePointer()->changeQualifier(EvqConst);
} else if ($1->isMatrix() && $1->getType().getQualifier() == EvqConst)
- $$->setType(TType($1->getBasicType(), EvqConst, $1->getNominalSize()));
+ $$->setType(TType($1->getBasicType(), $1->getPrecision(), EvqConst, $1->getNominalSize()));
else if ($1->isMatrix())
- $$->setType(TType($1->getBasicType(), EvqTemporary, $1->getNominalSize()));
+ $$->setType(TType($1->getBasicType(), $1->getPrecision(), EvqTemporary, $1->getNominalSize()));
else if ($1->isVector() && $1->getType().getQualifier() == EvqConst)
- $$->setType(TType($1->getBasicType(), EvqConst));
+ $$->setType(TType($1->getBasicType(), $1->getPrecision(), EvqConst));
else if ($1->isVector())
- $$->setType(TType($1->getBasicType(), EvqTemporary));
+ $$->setType(TType($1->getBasicType(), $1->getPrecision(), EvqTemporary));
else
$$->setType($1->getType());
}
@@ -347,19 +347,19 @@
$$ = $1;
}
else
- $$->setType(TType($1->getBasicType(), EvqConst, (int) (*$3.string).size()));
+ $$->setType(TType($1->getBasicType(), $1->getPrecision(), EvqConst, (int) (*$3.string).size()));
} else {
if (fields.num == 1) {
ConstantUnion *unionArray = new ConstantUnion[1];
unionArray->setIConst(fields.offsets[0]);
- TIntermTyped* index = parseContext->intermediate.addConstantUnion(unionArray, TType(EbtInt, EvqConst), $3.line);
+ TIntermTyped* index = parseContext->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), $3.line);
$$ = parseContext->intermediate.addIndex(EOpIndexDirect, $1, index, $2.line);
- $$->setType(TType($1->getBasicType()));
+ $$->setType(TType($1->getBasicType(), $1->getPrecision()));
} else {
TString vectorString = *$3.string;
TIntermTyped* index = parseContext->intermediate.addSwizzle(fields, $3.line);
$$ = parseContext->intermediate.addIndex(EOpVectorSwizzle, $1, index, $2.line);
- $$->setType(TType($1->getBasicType(),EvqTemporary, (int) vectorString.size()));
+ $$->setType(TType($1->getBasicType(), $1->getPrecision(), EvqTemporary, (int) vectorString.size()));
}
}
} else if ($1->isMatrix()) {
@@ -377,15 +377,15 @@
parseContext->recover();
ConstantUnion *unionArray = new ConstantUnion[1];
unionArray->setIConst(0);
- TIntermTyped* index = parseContext->intermediate.addConstantUnion(unionArray, TType(EbtInt, EvqConst), $3.line);
+ TIntermTyped* index = parseContext->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), $3.line);
$$ = parseContext->intermediate.addIndex(EOpIndexDirect, $1, index, $2.line);
- $$->setType(TType($1->getBasicType(), EvqTemporary, $1->getNominalSize()));
+ $$->setType(TType($1->getBasicType(), $1->getPrecision(),EvqTemporary, $1->getNominalSize()));
} else {
ConstantUnion *unionArray = new ConstantUnion[1];
unionArray->setIConst(fields.col * $1->getNominalSize() + fields.row);
- TIntermTyped* index = parseContext->intermediate.addConstantUnion(unionArray, TType(EbtInt, EvqConst), $3.line);
+ TIntermTyped* index = parseContext->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), $3.line);
$$ = parseContext->intermediate.addIndex(EOpIndexDirect, $1, index, $2.line);
- $$->setType(TType($1->getBasicType()));
+ $$->setType(TType($1->getBasicType(), $1->getPrecision()));
}
} else if ($1->getBasicType() == EbtStruct) {
bool fieldFound = false;
@@ -477,7 +477,7 @@
// Don't go through the symbol table for constructors.
// Their parameters will be verified algorithmically.
//
- TType type(EbtVoid); // use this to get the type back
+ TType type(EbtVoid, EbpUndefined); // use this to get the type back
if (parseContext->constructorErrorCheck($1.line, $1.intermNode, *fnCall, op, &type)) {
$$ = 0;
} else {
@@ -555,7 +555,7 @@
// Put on a dummy node for error recovery
ConstantUnion *unionArray = new ConstantUnion[1];
unionArray->setFConst(0.0f);
- $$ = parseContext->intermediate.addConstantUnion(unionArray, TType(EbtFloat, EvqConst), $1.line);
+ $$ = parseContext->intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpUndefined, EvqConst), $1.line);
parseContext->recover();
}
}
@@ -687,14 +687,14 @@
| IDENTIFIER {
if (parseContext->reservedErrorCheck($1.line, *$1.string))
parseContext->recover();
- TType type(EbtVoid);
+ TType type(EbtVoid, EbpUndefined);
TFunction *function = new TFunction($1.string, type);
$$ = function;
}
| FIELD_SELECTION {
if (parseContext->reservedErrorCheck($1.line, *$1.string))
parseContext->recover();
- TType type(EbtVoid);
+ TType type(EbtVoid, EbpUndefined);
TFunction *function = new TFunction($1.string, type);
$$ = function;
}
@@ -806,7 +806,7 @@
parseContext->recover();
ConstantUnion *unionArray = new ConstantUnion[1];
unionArray->setBConst(false);
- $$ = parseContext->intermediate.addConstantUnion(unionArray, TType(EbtBool, EvqConst), $2.line);
+ $$ = parseContext->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line);
}
}
| relational_expression RIGHT_ANGLE shift_expression {
@@ -816,7 +816,7 @@
parseContext->recover();
ConstantUnion *unionArray = new ConstantUnion[1];
unionArray->setBConst(false);
- $$ = parseContext->intermediate.addConstantUnion(unionArray, TType(EbtBool, EvqConst), $2.line);
+ $$ = parseContext->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line);
}
}
| relational_expression LE_OP shift_expression {
@@ -826,7 +826,7 @@
parseContext->recover();
ConstantUnion *unionArray = new ConstantUnion[1];
unionArray->setBConst(false);
- $$ = parseContext->intermediate.addConstantUnion(unionArray, TType(EbtBool, EvqConst), $2.line);
+ $$ = parseContext->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line);
}
}
| relational_expression GE_OP shift_expression {
@@ -836,7 +836,7 @@
parseContext->recover();
ConstantUnion *unionArray = new ConstantUnion[1];
unionArray->setBConst(false);
- $$ = parseContext->intermediate.addConstantUnion(unionArray, TType(EbtBool, EvqConst), $2.line);
+ $$ = parseContext->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line);
}
}
;
@@ -850,7 +850,7 @@
parseContext->recover();
ConstantUnion *unionArray = new ConstantUnion[1];
unionArray->setBConst(false);
- $$ = parseContext->intermediate.addConstantUnion(unionArray, TType(EbtBool, EvqConst), $2.line);
+ $$ = parseContext->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line);
} else if (($1->isArray() || $3->isArray()) && parseContext->extensionErrorCheck($2.line, "GL_3DL_array_objects"))
parseContext->recover();
}
@@ -861,7 +861,7 @@
parseContext->recover();
ConstantUnion *unionArray = new ConstantUnion[1];
unionArray->setBConst(false);
- $$ = parseContext->intermediate.addConstantUnion(unionArray, TType(EbtBool, EvqConst), $2.line);
+ $$ = parseContext->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line);
} else if (($1->isArray() || $3->isArray()) && parseContext->extensionErrorCheck($2.line, "GL_3DL_array_objects"))
parseContext->recover();
}
@@ -888,7 +888,7 @@
parseContext->recover();
ConstantUnion *unionArray = new ConstantUnion[1];
unionArray->setBConst(false);
- $$ = parseContext->intermediate.addConstantUnion(unionArray, TType(EbtBool, EvqConst), $2.line);
+ $$ = parseContext->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line);
}
}
;
@@ -902,7 +902,7 @@
parseContext->recover();
ConstantUnion *unionArray = new ConstantUnion[1];
unionArray->setBConst(false);
- $$ = parseContext->intermediate.addConstantUnion(unionArray, TType(EbtBool, EvqConst), $2.line);
+ $$ = parseContext->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line);
}
}
;
@@ -916,7 +916,7 @@
parseContext->recover();
ConstantUnion *unionArray = new ConstantUnion[1];
unionArray->setBConst(false);
- $$ = parseContext->intermediate.addConstantUnion(unionArray, TType(EbtBool, EvqConst), $2.line);
+ $$ = parseContext->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), $2.line);
}
}
;
@@ -1016,6 +1016,7 @@
$$ = $1.intermAggregate;
}
| PRECISION precision_qualifier type_specifier_no_prec SEMICOLON {
+ parseContext->symbolTable.setDefaultPrecision( $3.type, $2 );
$$ = 0;
}
;
@@ -1209,6 +1210,13 @@
init_declarator_list
: single_declaration {
$$ = $1;
+
+ if ($$.type.precision == EbpUndefined) {
+ $$.type.precision = parseContext->symbolTable.getDefaultPrecision($1.type.type);
+ if (parseContext->precisionErrorCheck($1.line, $$.type.precision, $1.type.type)) {
+ parseContext->recover();
+ }
+ }
}
| init_declarator_list COMMA IDENTIFIER {
$$.intermAggregate = parseContext->intermediate.growAggregate($1.intermNode, parseContext->intermediate.addSymbol(0, *$3.string, TType($1.type), $3.line), $3.line);
@@ -1593,7 +1601,7 @@
}
| precision_qualifier type_specifier_no_prec {
$$ = $2;
- $$.setPrecision($1);
+ $$.precision = $1;
}
;
@@ -1813,12 +1821,12 @@
struct_declarator
: IDENTIFIER {
- $$.type = new TType(EbtVoid);
+ $$.type = new TType(EbtVoid, EbpUndefined);
$$.line = $1.line;
$$.type->setFieldName(*$1.string);
}
| IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET {
- $$.type = new TType(EbtVoid);
+ $$.type = new TType(EbtVoid, EbpUndefined);
$$.line = $1.line;
$$.type->setFieldName(*$1.string);
diff --git a/src/compiler/intermOut.cpp b/src/compiler/intermOut.cpp
index a5bd069..70ead52 100644
--- a/src/compiler/intermOut.cpp
+++ b/src/compiler/intermOut.cpp
@@ -41,7 +41,7 @@
char *p = &buf[0];
if (qualifier != EvqTemporary && qualifier != EvqGlobal)
- p += sprintf(p, "%s ", getQualifierString());
+ p += sprintf(p, "%s %s ", getQualifierString(), getPrecisionString());
if (array)
p += sprintf(p, "array of ");
if (matrix)
diff --git a/src/compiler/intermediate.h b/src/compiler/intermediate.h
index ea7a962..b1241ca 100644
--- a/src/compiler/intermediate.h
+++ b/src/compiler/intermediate.h
@@ -238,6 +238,7 @@
virtual TBasicType getBasicType() const { return type.getBasicType(); }
virtual TQualifier getQualifier() const { return type.getQualifier(); }
+ virtual TPrecision getPrecision() const { return type.getPrecision(); }
virtual int getNominalSize() const { return type.getNominalSize(); }
virtual int getSize() const { return type.getInstanceSize(); }
virtual bool isMatrix() const { return type.isMatrix(); }
@@ -334,7 +335,7 @@
bool isConstructor() const;
virtual bool promote(TInfoSink&) { return true; }
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) {}
TOperator op;
};
@@ -416,7 +417,7 @@
class TIntermSelection : public TIntermTyped {
public:
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) :
TIntermTyped(type), condition(cond), trueBlock(trueB), falseBlock(falseB) {}
virtual void traverse(TIntermTraverser*);