Improve robustness of extension checking, and its intersection with ES 100 features.

git-svn-id: https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/tools/glslang@23388 e7fa87d3-cd2b-0410-9028-fcbf551c1848
This commit is contained in:
John Kessenich 2013-10-04 21:09:36 +00:00
parent c6b7e6350b
commit 816e9bc90b
13 changed files with 365 additions and 92 deletions

45
Test/100.frag Normal file
View File

@ -0,0 +1,45 @@
#version 100
int a[3] = { 2, 3, 4, }; // ERROR
int uint;
attribute vec4 v[3]; // ERROR
float f = 2; // ERROR
uniform block { // ERROR
int x;
};
void foo(float);
void main()
{
foo(3); // ERROR
int s = 1 << 4; // ERROR
s = 16 >> 2; // ERROR
if (a == a); // ERROR
int b, c;
b = c & 4; // ERROR
b = c % 4; // ERROR
b = c | 4; // ERROR
b >>= 2; // ERROR
b <<= 2; // ERROR
b %= 3; // ERROR
struct S {
float f;
float a[10];
} s1, s2;
s1 = s2; // ERROR
if (s1 == s2); // ERROR
if (s1 != s2); // ERROR
switch(b) { // ERROR
}
}
invariant gl_FragColor;
float fa[]; // ERROR

View File

@ -21,7 +21,7 @@ void main()
gu[2] = 4.0; // ERROR, overflow
}
g4 = foo(g5);
g4 = foo(g5); // ERROR
g5 = g4; // ERROR
gu = g4; // ERROR

View File

@ -0,0 +1,100 @@
ERROR: 0:3: '{ } style initializers' : not supported with this profile: es
ERROR: 0:3: 'initializer' : not supported for this version or the enabled extensions
ERROR: 0:3: '=' : cannot convert from 'const int' to '3-element array of mediump int'
ERROR: 0:7: 'attribute' : not supported in this stage: fragment
ERROR: 0:7: 'float' : type requires declaration of default precision qualifier
ERROR: 0:9: '=' : cannot convert from 'const int' to 'mediump float'
ERROR: 0:11: 'uniform block' : not supported for this version or the enabled extensions
ERROR: 0:19: 'foo' : no matching overloaded function found
ERROR: 0:20: 'bit shift left' : not supported for this version or the enabled extensions
ERROR: 0:21: 'bit shift right' : not supported for this version or the enabled extensions
ERROR: 0:22: 'array comparison' : not supported for this version or the enabled extensions
ERROR: 0:24: 'bitwise and' : not supported for this version or the enabled extensions
ERROR: 0:25: '%' : not supported for this version or the enabled extensions
ERROR: 0:26: 'bitwise inclusive or' : not supported for this version or the enabled extensions
ERROR: 0:27: 'bit-shift right assign' : not supported for this version or the enabled extensions
ERROR: 0:28: 'bit-shift left assign' : not supported for this version or the enabled extensions
ERROR: 0:29: '%=' : not supported for this version or the enabled extensions
ERROR: 0:36: 'array assignment' : not supported for this version or the enabled extensions
ERROR: 0:37: 'array comparison' : not supported for this version or the enabled extensions
ERROR: 0:38: 'array comparison' : not supported for this version or the enabled extensions
ERROR: 0:40: 'switch' : Reserved word.
ERROR: 0:40: 'switch statements' : not supported for this version or the enabled extensions
ERROR: 0:45: '' : array size required
ERROR: 23 compilation errors. No code generated.
ERROR: node is still EOpNull!
0:17 Function Definition: main( (void)
0:17 Function Parameters:
0:19 Sequence
0:19 Constant:
0:19 0.000000
0:20 Sequence
0:20 move second child to first child (mediump int)
0:20 's' (mediump int)
0:20 Constant:
0:20 16 (const int)
0:21 move second child to first child (mediump int)
0:21 's' (mediump int)
0:21 Constant:
0:21 4 (const int)
0:22 Test condition and select (void)
0:22 Condition
0:22 Compare Equal (bool)
0:22 'a' (3-element array of mediump int)
0:22 'a' (3-element array of mediump int)
0:22 true case is null
0:24 move second child to first child (mediump int)
0:24 'b' (mediump int)
0:24 bitwise and (mediump int)
0:24 'c' (mediump int)
0:24 Constant:
0:24 4 (const int)
0:25 move second child to first child (mediump int)
0:25 'b' (mediump int)
0:25 mod (mediump int)
0:25 'c' (mediump int)
0:25 Constant:
0:25 4 (const int)
0:26 move second child to first child (mediump int)
0:26 'b' (mediump int)
0:26 inclusive-or (mediump int)
0:26 'c' (mediump int)
0:26 Constant:
0:26 4 (const int)
0:27 right shift second child into first child (mediump int)
0:27 'b' (mediump int)
0:27 Constant:
0:27 2 (const int)
0:28 left shift second child into first child (mediump int)
0:28 'b' (mediump int)
0:28 Constant:
0:28 2 (const int)
0:29 mod second child into first child (mediump int)
0:29 'b' (mediump int)
0:29 Constant:
0:29 3 (const int)
0:36 move second child to first child (structure)
0:36 's1' (structure)
0:36 's2' (structure)
0:37 Test condition and select (void)
0:37 Condition
0:37 Compare Equal (bool)
0:37 's1' (structure)
0:37 's2' (structure)
0:37 true case is null
0:38 Test condition and select (void)
0:38 Condition
0:38 Compare Not Equal (bool)
0:38 's1' (structure)
0:38 's2' (structure)
0:38 true case is null
0:40 'b' (mediump int)
0:? Linker Objects
0:? 'a' (3-element array of mediump int)
0:? 'uint' (mediump int)
0:? 'v' (smooth in 3-element array of mediump 4-component vector of float)
0:? 'f' (mediump float)
0:? '__anon__0' (layout(shared ) uniform block)
0:? 'fa' (unsized array of mediump float)

View File

@ -4,14 +4,18 @@ ERROR: 0:9: 'arrayed type' : not supported for this version or the enabled exten
ERROR: 0:9: 'arrayed type' : not supported for this version or the enabled extensions
ERROR: 0:11: 'arrayed constructor' : not supported for this version or the enabled extensions
ERROR: 0:21: '[' : array index out of range '2'
ERROR: 0:24: 'array assignment' : not supported for this version or the enabled extensions
ERROR: 0:25: 'array assignment' : not supported for this version or the enabled extensions
ERROR: 0:25: 'assign' : cannot convert from '4-element array of mediump float' to '5-element array of mediump float'
ERROR: 0:26: 'array assignment' : not supported for this version or the enabled extensions
ERROR: 0:26: 'assign' : cannot convert from '4-element array of mediump float' to 'unsized array of mediump float'
ERROR: 0:28: 'foo' : no matching overloaded function found
ERROR: 0:31: 'arrayed constructor' : not supported for this version or the enabled extensions
ERROR: 0:31: 'array comparison' : not supported for this version or the enabled extensions
ERROR: 0:35: '[' : array index out of range '5'
ERROR: 0:38: '[' : array index out of range '1000'
ERROR: 0:39: '[' : array index out of range '-1'
ERROR: 13 compilation errors. No code generated.
ERROR: 17 compilation errors. No code generated.
ERROR: node is still EOpNull!
0:9 Function Definition: foo(f1[5]; (4-element array of mediump float)
@ -86,9 +90,9 @@ ERROR: node is still EOpNull!
0:35 5.000000
0:36 Function Call: foo(f1[5]; (4-element array of mediump float)
0:36 'u' (5-element array of mediump float)
0:38 move second child to first child (4-component vector of float)
0:38 direct index (fragColor 4-component vector of float)
0:38 'gl_FragData' (fragColor 32-element array of 4-component vector of float)
0:38 move second child to first child (mediump 4-component vector of float)
0:38 direct index (fragColor mediump 4-component vector of float)
0:38 'gl_FragData' (fragColor 32-element array of mediump 4-component vector of float)
0:38 Constant:
0:38 1000 (const int)
0:38 Constant:
@ -96,9 +100,9 @@ ERROR: node is still EOpNull!
0:38 1.000000
0:38 1.000000
0:38 1.000000
0:39 move second child to first child (4-component vector of float)
0:39 direct index (fragColor 4-component vector of float)
0:39 'gl_FragData' (fragColor 32-element array of 4-component vector of float)
0:39 move second child to first child (mediump 4-component vector of float)
0:39 direct index (fragColor mediump 4-component vector of float)
0:39 'gl_FragData' (fragColor 32-element array of mediump 4-component vector of float)
0:39 Constant:
0:39 -1 (const int)
0:39 Constant:
@ -106,9 +110,9 @@ ERROR: node is still EOpNull!
0:39 1.000000
0:39 1.000000
0:39 1.000000
0:40 move second child to first child (4-component vector of float)
0:40 direct index (fragColor 4-component vector of float)
0:40 'gl_FragData' (fragColor 32-element array of 4-component vector of float)
0:40 move second child to first child (mediump 4-component vector of float)
0:40 direct index (fragColor mediump 4-component vector of float)
0:40 'gl_FragData' (fragColor 32-element array of mediump 4-component vector of float)
0:40 Constant:
0:40 3 (const int)
0:40 Constant:

View File

@ -7,6 +7,7 @@ versionsClean.frag
versionsClean.vert
versionsErrors.frag
versionsErrors.vert
100.frag
120.vert
120.frag
130.frag

View File

@ -580,6 +580,18 @@ public:
virtual bool isMatrix() const { return matrixCols ? true : false; }
virtual bool isArray() const { return arraySizes != 0; }
virtual bool containsArray() const
{
if (isArray())
return true;
if (! structure)
return false;
for (unsigned int i = 0; i < structure->size(); ++i) {
if ((*structure)[i].type->containsArray())
return true;
}
return false;
}
int getArraySize() const { return arraySizes->sizes.front(); }
void setArraySizes(TArraySizes* s)
{

View File

@ -35,10 +35,16 @@
//
//
// Create strings that declare built-in definitions, add built-ins that
// cannot be expressed in the files, and establish mappings between
// Create strings that declare built-in definitions, add built-ins programmatically
// that cannot be expressed in the strings, and establish mappings between
// built-in functions and operators.
//
// Where to put a built-in:
// TBuiltIns::initialize(version,profile) context-independent textual built-ins; add them to the right string
// TBuiltIns::initialize(resources,...) context-dependent textual built-ins; add them to the right string
// IdentifyBuiltIns(...,symbolTable) context-independent programmatic additions/mappings to the symbol table
// IdentifyBuiltIns(...,symbolTable, resources) context-dependent programmatic additions/mappings to the symbol table
//
#include "../Include/intermediate.h"
#include "Initialize.h"
@ -50,14 +56,16 @@ const bool ForwardCompatibility = false;
TBuiltIns::TBuiltIns()
{
// Set up textual representations for making all the permutations
// of texturing/imaging functions.
prefixes[EbtFloat] = "";
prefixes[EbtInt] = "i";
prefixes[EbtUint] = "u";
postfixes[2] = "2";
postfixes[3] = "3";
postfixes[4] = "4";
// Map from symbolic class of texturing dimension to numeric dimensions.
dimMap[Esd1D] = 1;
dimMap[Esd2D] = 2;
dimMap[EsdRect] = 2;
@ -70,14 +78,16 @@ TBuiltIns::~TBuiltIns()
{
}
//
// Add all context-independent built-in functions and variables that are present
// for the given version and profile. Share common ones across stages, otherwise
// make stage-specific entries.
//
// Most built-ins variables can be added as simple text strings. Some need to
// be added programmatically, which is done later in IdentifyBuiltIns() below.
//
void TBuiltIns::initialize(int version, EProfile profile)
{
// TODO: Performance/Memory: consider an extra outer scope for built-ins common across all stages
//
// Initialize all the built-in strings for parsing.
//
{
//============================================================================
//
@ -1011,6 +1021,10 @@ void TBuiltIns::initialize(int version, EProfile profile)
//printf("%s\n", commonBuiltins.c_str();
}
//
// Helper function for initialize(), to add the second set of names for texturing,
// when adding context-independent built-in functions.
//
void TBuiltIns::add2ndGenerationSamplingImaging(int version, EProfile profile)
{
TBasicType bTypes[3] = { EbtFloat, EbtInt, EbtUint };
@ -1081,6 +1095,10 @@ void TBuiltIns::add2ndGenerationSamplingImaging(int version, EProfile profile)
}
}
//
// Helper function for add2ndGenerationSamplingImaging(),
// when adding context-independent built-in functions.
//
void TBuiltIns::addQueryFunctions(TSampler sampler, TString& typeName, int version, EProfile profile)
{
//
@ -1109,15 +1127,21 @@ void TBuiltIns::addQueryFunctions(TSampler sampler, TString& typeName, int versi
s.append(",int);\n");
else
s.append(");\n");
// TODO: 4.2 Functionality: imaging functions
}
//
// Helper function for add2ndGenerationSamplingImaging(),
// when adding context-independent built-in functions.
//
void TBuiltIns::addImageFunctions(TSampler sampler, TString& typeName, int version, EProfile profile)
{
// TODO: 4.2 Functionality: imaging functions
}
//
// Helper function for add2ndGenerationSamplingImaging(),
// when adding context-independent built-in functions.
//
void TBuiltIns::addSamplingFunctions(TSampler sampler, TString& typeName, int version, EProfile profile)
{
// make one string per stage to contain all functions of the passed-in type for that stage
@ -1297,6 +1321,11 @@ void TBuiltIns::addSamplingFunctions(TSampler sampler, TString& typeName, int ve
}
}
//
// Add context-dependent built-in functions and variables that are present
// for the given version and profile. Share common ones across stages, otherwise
// make stage-specific entries.
//
void TBuiltIns::initialize(const TBuiltInResource &resources, int version, EProfile profile, EShLanguage language)
{
//
@ -1448,6 +1477,12 @@ void TBuiltIns::initialize(const TBuiltInResource &resources, int version, EProf
}
}
//
// Finish adding/processing context-independent built-in symbols.
// 1) Programmatically add symbols that could not be added by simple text strings above.
// 2) Map built-in functions to operators, for those that will turn into an operation node
// instead of remaining a function call.
//
void IdentifyBuiltIns(int version, EProfile profile, EShLanguage language, TSymbolTable& symbolTable)
{
TPrecisionQualifier pq;
@ -1643,11 +1678,13 @@ void IdentifyBuiltIns(int version, EProfile profile, EShLanguage language, TSymb
}
}
//
// Add context-dependent (resource-specific) built-ins not yet handled. These
// would be ones that need to be programmatically added because they cannot
// be added by simple text strings.
//
void IdentifyBuiltIns(int version, EProfile profile, EShLanguage language, TSymbolTable& symbolTable, const TBuiltInResource &resources)
{
//
// Set resource-specific built-ins not yet handled.
//
switch(language) {
case EShLangFragment:

View File

@ -45,6 +45,15 @@
namespace glslang {
//
// This is made to hold parseable strings for almost all the built-in
// functions and variables for one specific combination of version
// and profile. (Some still need to be added programmatically.)
//
// The strings are organized by
// commonBuiltins: intersection of all stages' built-ins, processed just once
// stageBuiltins[]: anything a stage needs that's not in commonBuiltins
//
class TBuiltIns {
public:
POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator())
@ -64,7 +73,8 @@ protected:
TString commonBuiltins;
TString stageBuiltins[EShLangCount];
// Helpers for making text
// Helpers for making textual representations of the permutations
// of texturing/imaging functions.
const char* postfixes[5];
const char* prefixes[EbtNumTypes];
int dimMap[EsdNumDims];

View File

@ -527,7 +527,8 @@ TIntermTyped* TParseContext::handleDotDereference(TSourceLoc loc, TIntermTyped*
//
if (field == "length") {
profileRequires(loc, ENoProfile, 120, "GL_3DL_array_objects", ".length");
profileRequires(loc, ENoProfile, 120, GL_3DL_array_objects, ".length");
profileRequires(loc, EEsProfile, 300, 0, ".length");
result = intermediate.addMethod(base, TType(EbtInt), &field, loc);
} else
error(loc, "only the length method is supported for array", field.c_str(), "");
@ -851,8 +852,8 @@ TIntermTyped* TParseContext::handleFunctionCall(TSourceLoc loc, TFunction* fnCal
TFunction* TParseContext::handleConstructorCall(TSourceLoc loc, TPublicType& publicType)
{
if (publicType.arraySizes) {
profileRequires(loc, ENoProfile, 120, "GL_3DL_array_objects", "arrayed constructor");
profileRequires(loc, EEsProfile, 300, "GL_3DL_array_objects", "arrayed constructor");
profileRequires(loc, ENoProfile, 120, GL_3DL_array_objects, "arrayed constructor");
profileRequires(loc, EEsProfile, 300, 0, "arrayed constructor");
}
publicType.qualifier.precision = EpqNone;
@ -1648,8 +1649,10 @@ void TParseContext::arraySizeCheck(TSourceLoc loc, TIntermTyped* expr, int& size
//
bool TParseContext::arrayQualifierError(TSourceLoc loc, const TQualifier& qualifier)
{
if (qualifier.storage == EvqConst)
profileRequires(loc, ENoProfile, 120, "GL_3DL_array_objects", "const array");
if (qualifier.storage == EvqConst) {
profileRequires(loc, ENoProfile, 120, GL_3DL_array_objects, "const array");
profileRequires(loc, EEsProfile, 300, 0, "const array");
}
if (qualifier.storage == EvqVaryingIn && language == EShLangVertex) {
requireProfile(loc, ~EEsProfile, "vertex input arrays");
@ -1893,6 +1896,15 @@ void TParseContext::nestedStructCheck(TSourceLoc loc)
++structNestingLevel;
}
void TParseContext::arrayObjectCheck(TSourceLoc loc, const TType& type, const char* op)
{
// Some versions don't allow comparing arrays or structures containing arrays
if (type.containsArray()) {
profileRequires(loc, ENoProfile, 120, GL_3DL_array_objects, op);
profileRequires(loc, EEsProfile, 300, 0, op);
}
}
//
// Layout qualifier stuff.
//
@ -2020,8 +2032,10 @@ TIntermNode* TParseContext::declareVariable(TSourceLoc loc, TString& identifier,
declareArray(loc, identifier, type, variable, newDeclaration);
}
if (initializer)
profileRequires(loc, ENoProfile, 120, "GL_3DL_array_objects", "initializer");
if (initializer) {
profileRequires(loc, ENoProfile, 120, GL_3DL_array_objects, "initializer");
profileRequires(loc, EEsProfile, 300, 0, "initializer");
}
} else {
// non-array case
if (! variable)

View File

@ -115,6 +115,7 @@ public:
void paramCheck(TSourceLoc, TStorageQualifier qualifier, TType* type);
void nestedBlockCheck(TSourceLoc);
void nestedStructCheck(TSourceLoc);
void arrayObjectCheck(TSourceLoc, const TType&, const char* op);
void setLayoutQualifier(TSourceLoc, TPublicType&, TString&);
void setLayoutQualifier(TSourceLoc, TPublicType&, TString&, int);
@ -161,7 +162,6 @@ public:
protected:
const char* getPreamble();
TExtensionBehavior getExtensionBehavior(const char* behavior);
void nonInitConstCheck(TSourceLoc, TString& identifier, TType& type);
TVariable* declareNonArray(TSourceLoc, TString& identifier, TType&, bool& newDeclaration);
void declareArray(TSourceLoc, TString& identifier, const TType&, TVariable*&, bool& newDeclaration);

View File

@ -48,7 +48,7 @@
// To add a new hypothetical "Feature F" to the front end, where an extension
// "XXX_extension_X" can be used to enable the feature, do the following.
//
// 1) Understand that specific features are what are error-checked for, not
// OVERVIEW: Specific features are what are error-checked for, not
// extensions: A specific Feature F might be enabled by an extension, or a
// particular version in a particular profile, or a stage, or combinations, etc.
//
@ -66,11 +66,17 @@
// will then always continue as if the tested feature was enabled.
//
// There is typically no if-testing or conditional parsing, just insertion of requirements.
// However, if symbols specific to the extension are added (step 5), they will
// only be added under tests that the minimum version and profile are present.
//
// 1) Add a symbol name for the extension string at the bottom of Versions.h:
//
// const char* const XXX_extension_X = "XXX_extension_X";
//
// 2) Add extension initialization to TParseContext::initializeExtensionBehavior(),
// the first function below:
//
// extensionBehavior["XXX_extension_X"] = EBhDisable;
// extensionBehavior[XXX_extension_X] = EBhDisable;
//
// 3) Insert a profile check in the feature's path (unless all profiles support the feature,
// for some version level). That is, call requireProfile() to constrain the profiles, e.g.:
@ -90,7 +96,7 @@
// profileRequires(loc,
// ECoreProfile | ECompatibilityProfile,
// 420, // 0 if no version incorporated the feature into the core spec.
// "XXX_extension_X", // can be a list of extensions that all add the feature
// XXX_extension_X, // can be a list of extensions that all add the feature
// "Feature F");
//
// This allows the feature if either A) one of the extensions is enabled or
@ -117,6 +123,9 @@
//
// ~EEsProfile
//
// 5) If built-in symbols are added by the extension, add them in Initialize.cpp; see
// the comment at the top of that file for where to put them.
//
#include "ParseHelper.h"
@ -129,10 +138,14 @@ namespace glslang {
//
void TParseContext::initializeExtensionBehavior()
{
extensionBehavior["GL_ARB_texture_rectangle"] = EBhDisable;
extensionBehavior["GL_3DL_array_objects"] = EBhDisable;
extensionBehavior[GL_ARB_texture_rectangle] = EBhDisable;
extensionBehavior[GL_3DL_array_objects] = EBhDisable;
extensionBehavior[GL_ARB_shading_language_420pack] = EBhDisable;
}
//
// Map from profile enum to externally readable text name.
//
const char* ProfileName(EProfile profile)
{
switch (profile) {
@ -159,6 +172,9 @@ void TParseContext::requireProfile(TSourceLoc loc, int profileMask, const char *
error(loc, "not supported with this profile:", featureDesc, ProfileName(profile));
}
//
// Map from stage enum to externally readable text name.
//
const char* StageName(EShLanguage stage)
{
switch(stage) {
@ -274,32 +290,27 @@ void TParseContext::requireNotRemoved(TSourceLoc loc, int profileMask, int remov
}
//
// Translate from text string of extension's behavior to enum.
// Change the current state of an extension's behavior.
//
TExtensionBehavior TParseContext::getExtensionBehavior(const char* behavior)
{
if (! strcmp("require", behavior))
return EBhRequire;
else if (! strcmp("enable", behavior))
return EBhEnable;
else if (! strcmp("disable", behavior))
return EBhDisable;
else if (! strcmp("warn", behavior))
return EBhWarn;
else {
error(currentLoc, "behavior not supported", "#extension", behavior);
return EBhDisable;
}
}
void TParseContext::updateExtensionBehavior(const char* extName, const char* behaviorString)
{
TExtensionBehavior behavior = getExtensionBehavior(behaviorString);
TMap<TString, TExtensionBehavior>:: iterator iter;
TString msg;
// Translate from text string of extension's behavior to an enum.
TExtensionBehavior behavior = EBhDisable;
if (! strcmp("require", behaviorString))
behavior = EBhRequire;
else if (! strcmp("enable", behaviorString))
behavior = EBhEnable;
else if (! strcmp("disable", behaviorString))
behavior = EBhDisable;
else if (! strcmp("warn", behaviorString))
behavior = EBhWarn;
else
error(currentLoc, "behavior not supported", "#extension", behaviorString);
// special case for the 'all' extension
// Update the current behavior
TMap<TString, TExtensionBehavior>::iterator iter;
if (! strcmp(extName, "all")) {
// special case for the 'all' extension; apply it to every extension present
if (behavior == EBhRequire || behavior == EBhEnable) {
error(currentLoc, "extension 'all' cannot have 'require' or 'enable' behavior", "#extension", "");
return;
@ -308,6 +319,7 @@ void TParseContext::updateExtensionBehavior(const char* extName, const char* beh
iter->second = behavior;
}
} else {
// Do the update for this single extension
iter = extensionBehavior.find(TString(extName));
if (iter == extensionBehavior.end()) {
switch (behavior) {

View File

@ -40,16 +40,6 @@
// Help manage multiple profiles, versions, extensions etc.
//
//
// The behaviors from "#extension extension_name : behavior"
//
typedef enum {
EBhRequire,
EBhEnable,
EBhWarn,
EBhDisable
} TExtensionBehavior;
//
// Profiles are set up for masking operations, so queries can be done on multiple
// profiles at the same time.
@ -65,4 +55,26 @@ typedef enum {
EEsProfile = (1 << 3)
} EProfile;
namespace glslang {
//
// The behaviors from the GLSL "#extension extension_name : behavior"
//
typedef enum {
EBhRequire,
EBhEnable,
EBhWarn,
EBhDisable
} TExtensionBehavior;
//
// Symbolic names for extensions. Strings may be directly used when calling the
// functions, but better to have the compiler do spelling checks.
//
const char* const GL_ARB_texture_rectangle = "GL_ARB_texture_rectangle";
const char* const GL_3DL_array_objects = "GL_3DL_array_objects";
const char* const GL_ARB_shading_language_420pack = "GL_ARB_shading_language_420pack";
} // end namespace glslang
#endif // _VERSIONS_INCLUDED_

View File

@ -463,6 +463,7 @@ multiplicative_expression
}
}
| multiplicative_expression PERCENT unary_expression {
parseContext.fullIntegerCheck($2.loc, "%");
$$ = parseContext.intermediate.addBinaryMath(EOpMod, $1, $3, $2.loc);
if ($$ == 0) {
parseContext.binaryOpError($2.loc, "%", $1->getCompleteString(), $3->getCompleteString());
@ -552,24 +553,24 @@ relational_expression
equality_expression
: relational_expression { $$ = $1; }
| equality_expression EQ_OP relational_expression {
parseContext.arrayObjectCheck($2.loc, $1->getType(), "array comparison");
$$ = parseContext.intermediate.addBinaryMath(EOpEqual, $1, $3, $2.loc);
if ($$ == 0) {
parseContext.binaryOpError($2.loc, "==", $1->getCompleteString(), $3->getCompleteString());
TConstUnionArray unionArray(1);
unionArray[0].setBConst(false);
$$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtBool, EvqConst), $2.loc);
} else if (($1->isArray() || $3->isArray()))
parseContext.profileRequires($2.loc, ENoProfile, 120, "GL_3DL_array_objects", "==");
}
}
| equality_expression NE_OP relational_expression {
parseContext.arrayObjectCheck($2.loc, $1->getType(), "array comparison");
$$ = parseContext.intermediate.addBinaryMath(EOpNotEqual, $1, $3, $2.loc);
if ($$ == 0) {
parseContext.binaryOpError($2.loc, "!=", $1->getCompleteString(), $3->getCompleteString());
TConstUnionArray unionArray(1);
unionArray[0].setBConst(false);
$$ = parseContext.intermediate.addConstantUnion(unionArray, TType(EbtBool, EvqConst), $2.loc);
} else if (($1->isArray() || $3->isArray()))
parseContext.profileRequires($2.loc, ENoProfile, 120, "GL_3DL_array_objects", "!=");
}
}
;
@ -664,23 +665,42 @@ conditional_expression
assignment_expression
: conditional_expression { $$ = $1; }
| unary_expression assignment_operator assignment_expression {
parseContext.arrayObjectCheck($2.loc, $1->getType(), "array assignment");
parseContext.lValueErrorCheck($2.loc, "assign", $1);
$$ = parseContext.intermediate.addAssign($2.op, $1, $3, $2.loc);
if ($$ == 0) {
parseContext.assignError($2.loc, "assign", $1->getCompleteString(), $3->getCompleteString());
$$ = $1;
} else if (($1->isArray() || $3->isArray()))
parseContext.profileRequires($2.loc, ENoProfile, 120, "GL_3DL_array_objects", "=");
}
}
;
assignment_operator
: EQUAL { $$.loc = $1.loc; $$.op = EOpAssign; }
| MUL_ASSIGN { $$.loc = $1.loc; $$.op = EOpMulAssign; }
| DIV_ASSIGN { $$.loc = $1.loc; $$.op = EOpDivAssign; }
| MOD_ASSIGN { $$.loc = $1.loc; $$.op = EOpModAssign; }
| ADD_ASSIGN { $$.loc = $1.loc; $$.op = EOpAddAssign; }
| SUB_ASSIGN { $$.loc = $1.loc; $$.op = EOpSubAssign; }
: EQUAL {
$$.loc = $1.loc;
$$.op = EOpAssign;
}
| MUL_ASSIGN {
$$.loc = $1.loc;
$$.op = EOpMulAssign;
}
| DIV_ASSIGN {
$$.loc = $1.loc;
$$.op = EOpDivAssign;
}
| MOD_ASSIGN {
parseContext.fullIntegerCheck($1.loc, "%=");
$$.loc = $1.loc;
$$.op = EOpModAssign;
}
| ADD_ASSIGN {
$$.loc = $1.loc;
$$.op = EOpAddAssign;
}
| SUB_ASSIGN {
$$.loc = $1.loc;
$$.op = EOpSubAssign;
}
| LEFT_ASSIGN {
parseContext.fullIntegerCheck($1.loc, "bit-shift left assign");
$$.loc = $1.loc; $$.op = EOpLeftShiftAssign;
@ -853,7 +873,7 @@ parameter_declarator
// Type + name
: type_specifier IDENTIFIER {
if ($1.arraySizes) {
parseContext.profileRequires($1.loc, ENoProfile, 120, "GL_3DL_array_objects", "arrayed type");
parseContext.profileRequires($1.loc, ENoProfile, 120, GL_3DL_array_objects, "arrayed type");
parseContext.profileRequires($1.loc, EEsProfile, 300, 0, "arrayed type");
parseContext.arraySizeRequiredCheck($1.loc, $1.arraySizes->getSize());
}
@ -868,7 +888,7 @@ parameter_declarator
}
| type_specifier IDENTIFIER array_specifier {
if ($1.arraySizes) {
parseContext.profileRequires($1.loc, ENoProfile, 120, "GL_3DL_array_objects", "arrayed type");
parseContext.profileRequires($1.loc, ENoProfile, 120, GL_3DL_array_objects, "arrayed type");
parseContext.profileRequires($1.loc, EEsProfile, 300, 0, "arrayed type");
parseContext.arraySizeRequiredCheck($1.loc, $1.arraySizes->getSize());
}
@ -989,7 +1009,7 @@ fully_specified_type
$$ = $1;
if ($1.arraySizes) {
parseContext.profileRequires($1.loc, ENoProfile, 120, "GL_3DL_array_objects", "arrayed type");
parseContext.profileRequires($1.loc, ENoProfile, 120, GL_3DL_array_objects, "arrayed type");
parseContext.profileRequires($1.loc, EEsProfile, 300, 0, "arrayed type");
if (parseContext.profile == EEsProfile)
parseContext.arraySizeRequiredCheck($1.loc, $1.arraySizes->getSize());
@ -1001,7 +1021,7 @@ fully_specified_type
parseContext.globalQualifierFix($1.loc, $1.qualifier, $2);
if ($2.arraySizes) {
parseContext.profileRequires($2.loc, ENoProfile, 120, "GL_3DL_array_objects", "arrayed type");
parseContext.profileRequires($2.loc, ENoProfile, 120, GL_3DL_array_objects, "arrayed type");
parseContext.profileRequires($2.loc, EEsProfile, 300, 0, "arrayed type");
if (parseContext.profile == EEsProfile)
parseContext.arraySizeRequiredCheck($2.loc, $2.arraySizes->getSize());
@ -1676,28 +1696,28 @@ type_specifier_nonarray
$$.sampler.set(EbtUint, EsdCube, true);
}
| SAMPLER2DRECT {
parseContext.profileRequires($1.loc, ENoProfile, 140, "GL_ARB_texture_rectangle", "rectangle texture");
parseContext.profileRequires($1.loc, ENoProfile, 140, GL_ARB_texture_rectangle, "rectangle texture");
$$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
$$.basicType = EbtSampler;
$$.sampler.set(EbtFloat, EsdRect);
}
| SAMPLER2DRECTSHADOW {
parseContext.profileRequires($1.loc, ECoreProfile, 140, "GL_ARB_texture_rectangle", "rectangle texture");
parseContext.profileRequires($1.loc, ECoreProfile, 140, GL_ARB_texture_rectangle, "rectangle texture");
$$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
$$.basicType = EbtSampler;
$$.sampler.set(EbtFloat, EsdRect, false, true);
}
| ISAMPLER2DRECT {
parseContext.profileRequires($1.loc, ECoreProfile, 140, "GL_ARB_texture_rectangle", "rectangle texture");
parseContext.profileRequires($1.loc, ECoreProfile, 140, GL_ARB_texture_rectangle, "rectangle texture");
$$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
$$.basicType = EbtSampler;
$$.sampler.set(EbtInt, EsdRect);
}
| USAMPLER2DRECT {
parseContext.profileRequires($1.loc, ECoreProfile, 140, "GL_ARB_texture_rectangle", "rectangle texture");
parseContext.profileRequires($1.loc, ECoreProfile, 140, GL_ARB_texture_rectangle, "rectangle texture");
$$.init($1.loc, parseContext.symbolTable.atGlobalLevel());
$$.basicType = EbtSampler;
@ -1992,7 +2012,7 @@ struct_declaration_list
struct_declaration
: type_specifier struct_declarator_list SEMICOLON {
if ($1.arraySizes) {
parseContext.profileRequires($1.loc, ENoProfile, 120, "GL_3DL_array_objects", "arrayed type");
parseContext.profileRequires($1.loc, ENoProfile, 120, GL_3DL_array_objects, "arrayed type");
parseContext.profileRequires($1.loc, EEsProfile, 300, 0, "arrayed type");
if (parseContext.profile == EEsProfile)
parseContext.arraySizeRequiredCheck($1.loc, $1.arraySizes->getSize());
@ -2010,7 +2030,7 @@ struct_declaration
}
| type_qualifier type_specifier struct_declarator_list SEMICOLON {
if ($2.arraySizes) {
parseContext.profileRequires($2.loc, ENoProfile, 120, "GL_3DL_array_objects", "arrayed type");
parseContext.profileRequires($2.loc, ENoProfile, 120, GL_3DL_array_objects, "arrayed type");
parseContext.profileRequires($2.loc, EEsProfile, 300, 0, "arrayed type");
if (parseContext.profile == EEsProfile)
parseContext.arraySizeRequiredCheck($2.loc, $2.arraySizes->getSize());
@ -2062,9 +2082,15 @@ initializer
$$ = $1;
}
| LEFT_BRACE initializer_list RIGHT_BRACE {
const char* initFeature = "{ } style initializers";
parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, initFeature);
parseContext.profileRequires($1.loc, ECoreProfile | ECompatibilityProfile, 420, GL_ARB_shading_language_420pack, initFeature);
$$ = $2;
}
| LEFT_BRACE initializer_list COMMA RIGHT_BRACE {
const char* initFeature = "{ } style initializers";
parseContext.requireProfile($1.loc, ECoreProfile | ECompatibilityProfile, initFeature);
parseContext.profileRequires($1.loc, ECoreProfile | ECompatibilityProfile, 420, GL_ARB_shading_language_420pack, initFeature);
$$ = $2;
}
;