From: John Kessenich Date: Fri, 4 Oct 2013 21:09:36 +0000 (+0000) Subject: Improve robustness of extension checking, and its intersection with ES 100 features. X-Git-Tag: upstream/0.1~904 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=816e9bc90b81bb0e0ec4b578b5201fb487dfdbae;p=platform%2Fupstream%2Fglslang.git 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 --- diff --git a/Test/100.frag b/Test/100.frag new file mode 100644 index 0000000..529b360 --- /dev/null +++ b/Test/100.frag @@ -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 diff --git a/Test/array100.frag b/Test/array100.frag index 6f0feb4..596e41b 100644 --- a/Test/array100.frag +++ b/Test/array100.frag @@ -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 diff --git a/Test/baseResults/100.frag.out b/Test/baseResults/100.frag.out new file mode 100644 index 0000000..fc1369d --- /dev/null +++ b/Test/baseResults/100.frag.out @@ -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) + diff --git a/Test/baseResults/array100.frag.out b/Test/baseResults/array100.frag.out index 05b5797..ce9072b 100644 --- a/Test/baseResults/array100.frag.out +++ b/Test/baseResults/array100.frag.out @@ -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: diff --git a/Test/testlist b/Test/testlist index 31cfa75..8df4088 100644 --- a/Test/testlist +++ b/Test/testlist @@ -7,6 +7,7 @@ versionsClean.frag versionsClean.vert versionsErrors.frag versionsErrors.vert +100.frag 120.vert 120.frag 130.frag diff --git a/glslang/Include/Types.h b/glslang/Include/Types.h index 5a2c9c6..11e43a2 100644 --- a/glslang/Include/Types.h +++ b/glslang/Include/Types.h @@ -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) { diff --git a/glslang/MachineIndependent/Initialize.cpp b/glslang/MachineIndependent/Initialize.cpp index f26dc31..ed94754 100644 --- a/glslang/MachineIndependent/Initialize.cpp +++ b/glslang/MachineIndependent/Initialize.cpp @@ -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: diff --git a/glslang/MachineIndependent/Initialize.h b/glslang/MachineIndependent/Initialize.h index 661b98c..2b0c6b0 100644 --- a/glslang/MachineIndependent/Initialize.h +++ b/glslang/MachineIndependent/Initialize.h @@ -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]; diff --git a/glslang/MachineIndependent/ParseHelper.cpp b/glslang/MachineIndependent/ParseHelper.cpp index fe884bf..9725ff2 100644 --- a/glslang/MachineIndependent/ParseHelper.cpp +++ b/glslang/MachineIndependent/ParseHelper.cpp @@ -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) diff --git a/glslang/MachineIndependent/ParseHelper.h b/glslang/MachineIndependent/ParseHelper.h index 4c3f75b..1d874ff 100644 --- a/glslang/MachineIndependent/ParseHelper.h +++ b/glslang/MachineIndependent/ParseHelper.h @@ -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); diff --git a/glslang/MachineIndependent/Versions.cpp b/glslang/MachineIndependent/Versions.cpp index 0afd7fd..aa6fc52 100644 --- a/glslang/MachineIndependent/Versions.cpp +++ b/glslang/MachineIndependent/Versions.cpp @@ -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:: 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::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) { diff --git a/glslang/MachineIndependent/Versions.h b/glslang/MachineIndependent/Versions.h index d917b5d..94fd644 100644 --- a/glslang/MachineIndependent/Versions.h +++ b/glslang/MachineIndependent/Versions.h @@ -41,16 +41,6 @@ // // -// 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_ diff --git a/glslang/MachineIndependent/glslang.y b/glslang/MachineIndependent/glslang.y index 9496e27..17f3b27 100644 --- a/glslang/MachineIndependent/glslang.y +++ b/glslang/MachineIndependent/glslang.y @@ -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; } ;