HLSL: phase 2c: use lValueErrorCheck in HLSL FE
This commit splits lValueErrorCheck into machine dependent and independent parts. The GLSL form in TParseContext inherits from and invokes the machine dependent part in TParseContextBase. The base form checks language independent things. This split does not change the set of errors tested for: the test results are identical. The new base class interface is now used from the HLSL FE to test lvalues. There was one test diff due to this, where the test was writing to a uniform. It still does the same indirections, but does not attempt a uniform write.
This commit is contained in:
parent
90707966ea
commit
0de16da2c0
7 changed files with 222 additions and 130 deletions
|
|
@ -1902,14 +1902,14 @@ void TParseContext::variableCheck(TIntermTyped*& nodePtr)
|
|||
// 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.
|
||||
//
|
||||
// Returns true if the was an error.
|
||||
// Returns true if there was an error.
|
||||
//
|
||||
bool TParseContext::lValueErrorCheck(const TSourceLoc& loc, const char* op, TIntermTyped* node)
|
||||
{
|
||||
TIntermBinary* binaryNode = node->getAsBinaryNode();
|
||||
|
||||
if (binaryNode) {
|
||||
bool errorReturn;
|
||||
bool errorReturn = false;
|
||||
|
||||
switch(binaryNode->getOp()) {
|
||||
case EOpIndexDirect:
|
||||
|
|
@ -1928,9 +1928,9 @@ bool TParseContext::lValueErrorCheck(const TSourceLoc& loc, const char* op, TInt
|
|||
}
|
||||
}
|
||||
|
||||
// fall through
|
||||
break; // left node is checked by base class
|
||||
case EOpIndexDirectStruct:
|
||||
return lValueErrorCheck(loc, op, binaryNode->getLeft());
|
||||
break; // left node is checked by base class
|
||||
case EOpVectorSwizzle:
|
||||
errorReturn = lValueErrorCheck(loc, op, binaryNode->getLeft());
|
||||
if (!errorReturn) {
|
||||
|
|
@ -1955,12 +1955,18 @@ bool TParseContext::lValueErrorCheck(const TSourceLoc& loc, const char* op, TInt
|
|||
default:
|
||||
break;
|
||||
}
|
||||
error(loc, " l-value required", op, "", "");
|
||||
|
||||
return true;
|
||||
if (errorReturn) {
|
||||
error(loc, " l-value required", op, "", "");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Let the base class check errors
|
||||
if (TParseContextBase::lValueErrorCheck(loc, op, node))
|
||||
return true;
|
||||
|
||||
// GLSL specific
|
||||
const char* symbol = nullptr;
|
||||
TIntermSymbol* symNode = node->getAsSymbolNode();
|
||||
if (symNode != nullptr)
|
||||
|
|
@ -1968,19 +1974,12 @@ bool TParseContext::lValueErrorCheck(const TSourceLoc& loc, const char* op, TInt
|
|||
|
||||
const char* message = nullptr;
|
||||
switch (node->getQualifier().storage) {
|
||||
case EvqConst: message = "can't modify a const"; break;
|
||||
case EvqConstReadOnly: message = "can't modify a const"; break;
|
||||
case EvqVaryingIn: message = "can't modify shader input"; break;
|
||||
case EvqInstanceId: message = "can't modify gl_InstanceID"; break;
|
||||
case EvqVertexId: message = "can't modify gl_VertexID"; break;
|
||||
case EvqFace: message = "can't modify gl_FrontFace"; break;
|
||||
case EvqFragCoord: message = "can't modify gl_FragCoord"; break;
|
||||
case EvqPointCoord: message = "can't modify gl_PointCoord"; break;
|
||||
case EvqUniform: message = "can't modify a uniform"; break;
|
||||
case EvqBuffer:
|
||||
if (node->getQualifier().readonly)
|
||||
message = "can't modify a readonly buffer";
|
||||
break;
|
||||
case EvqFragDepth:
|
||||
intermediate.setDepthReplacing();
|
||||
// "In addition, it is an error to statically write to gl_FragDepth in the fragment shader."
|
||||
|
|
@ -1989,22 +1988,7 @@ bool TParseContext::lValueErrorCheck(const TSourceLoc& loc, const char* op, TInt
|
|||
break;
|
||||
|
||||
default:
|
||||
//
|
||||
// Type that can't be written to?
|
||||
//
|
||||
switch (node->getBasicType()) {
|
||||
case EbtSampler:
|
||||
message = "can't modify a sampler";
|
||||
break;
|
||||
case EbtAtomicUint:
|
||||
message = "can't modify an atomic_uint";
|
||||
break;
|
||||
case EbtVoid:
|
||||
message = "can't modify void";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (message == nullptr && binaryNode == nullptr && symNode == nullptr) {
|
||||
|
|
@ -2013,7 +1997,6 @@ bool TParseContext::lValueErrorCheck(const TSourceLoc& loc, const char* op, TInt
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Everything else is okay, no error.
|
||||
//
|
||||
|
|
@ -2034,30 +2017,14 @@ bool TParseContext::lValueErrorCheck(const TSourceLoc& loc, const char* op, TInt
|
|||
// Test for and give an error if the node can't be read from.
|
||||
void TParseContext::rValueErrorCheck(const TSourceLoc& loc, const char* op, TIntermTyped* node)
|
||||
{
|
||||
if (! node)
|
||||
return;
|
||||
// Let the base class check errors
|
||||
TParseContextBase::rValueErrorCheck(loc, op, node);
|
||||
|
||||
TIntermBinary* binaryNode = node->getAsBinaryNode();
|
||||
if (binaryNode) {
|
||||
switch(binaryNode->getOp()) {
|
||||
case EOpIndexDirect:
|
||||
case EOpIndexIndirect:
|
||||
case EOpIndexDirectStruct:
|
||||
case EOpVectorSwizzle:
|
||||
rValueErrorCheck(loc, op, binaryNode->getLeft());
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
TIntermSymbol* symNode = node->getAsSymbolNode();
|
||||
if (symNode && symNode->getQualifier().writeonly)
|
||||
error(loc, "can't read from writeonly object: ", op, symNode->getName().c_str());
|
||||
#ifdef AMD_EXTENSIONS
|
||||
else if (symNode && symNode->getQualifier().explicitInterp)
|
||||
error(loc, "can't read from explicitly-interpolated object: ", op, symNode->getName().c_str());
|
||||
TIntermSymbol* symNode = node->getAsSymbolNode();
|
||||
if (!(symNode && symNode->getQualifier().writeonly)) // base class checks
|
||||
if (symNode && symNode->getQualifier().explicitInterp)
|
||||
error(loc, "can't read from explicitly-interpolated object: ", op, symNode->getName().c_str());
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue